18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant - WPA state machine and EAPOL-Key processing 3c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/aes_wrap.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/crypto.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eapol_supp/eapol_supp_sm.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "preauth.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "pmksa_cache.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_i.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_ie.h" 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "peerkey.h" 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_eapol_key_send - Send WPA/RSN EAPOL-Key message 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @kck: Key Confirmation Key (KCK, part of PTK) 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ver: Version field from Key Info 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dest: Destination address for the frame 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @proto: Ethertype (usually ETH_P_EAPOL) 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @msg: EAPOL-Key message 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @msg_len: Length of message 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key_mic: Pointer to the buffer to which the EAPOL-Key MIC is written 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ver, const u8 *dest, u16 proto, 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *msg, size_t msg_len, u8 *key_mic) 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (is_zero_ether_addr(dest) && is_zero_ether_addr(sm->bssid)) { 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Association event was not yet received; try to fetch 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * BSSID from the driver. 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_get_bssid(sm, sm->bssid) < 0) { 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Failed to read BSSID for " 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAPOL-Key destination address"); 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dest = sm->bssid; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Use BSSID (" MACSTR 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ") as the destination for EAPOL-Key", 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(dest)); 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_mic && 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_mic(kck, ver, msg, msg_len, key_mic)) { 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Failed to generate EAPOL-Key " 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "version %d MIC", ver); 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", kck, 16); 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Derived Key MIC", key_mic, 16); 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key", msg, msg_len); 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_ether_send(sm, dest, proto, msg, msg_len); 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_notify_tx_eapol_key(sm->eapol); 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtout: 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(msg); 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_key_request - Send EAPOL-Key Request 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @error: Indicate whether this is an Michael MIC error report 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pairwise: 1 = error report for pairwise packet, 0 = for group packet 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Send an EAPOL-Key Request to the current authenticator. This function is 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * used to request rekeying and it is usually called when a local Michael MIC 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * failure is detected. 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rlen; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *reply; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int key_info, ver; 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 bssid[ETH_ALEN], *rbuf; 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 92f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (sm->key_mgmt == WPA_KEY_MGMT_OSEN) 93f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ver = WPA_KEY_INFO_TYPE_AKM_DEFINED; 94f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt else if (wpa_key_mgmt_ft(sm->key_mgmt) || 95f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_key_mgmt_sha256(sm->key_mgmt)) 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = WPA_KEY_INFO_TYPE_AES_128_CMAC; 9761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt else if (sm->pairwise_cipher != WPA_CIPHER_TKIP) 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_get_bssid(sm, bssid) < 0) { 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Failed to read BSSID for EAPOL-Key request"); 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(*reply), &rlen, (void *) &reply); 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 113f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt reply->type = (sm->proto == WPA_PROTO_RSN || 114f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sm->proto == WPA_PROTO_OSEN) ? 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = WPA_KEY_INFO_REQUEST | ver; 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->ptk_set) 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info |= WPA_KEY_INFO_MIC; 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (error) 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info |= WPA_KEY_INFO_ERROR; 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pairwise) 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info |= WPA_KEY_INFO_KEY_TYPE; 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_info, key_info); 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_length, 0); 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply->replay_counter, sm->request_counter, 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_data_length, 0); 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Sending EAPOL-Key Request (error=%d " 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pairwise=%d ptk_set=%d len=%lu)", 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt error, pairwise, sm->ptk_set, (unsigned long) rlen); 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL, 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf, rlen, key_info & WPA_KEY_INFO_MIC ? 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply->key_mic : NULL); 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_get_pmk(struct wpa_sm *sm, 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pmkid) 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int abort_cached = 0; 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmkid && !sm->cur_pmksa) { 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* When using drivers that generate RSN IE, wpa_supplicant may 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * not have enough time to get the association information 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * event before receiving this 1/4 message, so try to find a 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * matching PMKSA cache entry here. */ 152c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sm->cur_pmksa = pmksa_cache_get(sm->pmksa, src_addr, pmkid, 153c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt NULL); 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->cur_pmksa) { 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: found matching PMKID from PMKSA cache"); 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: no matching PMKID found"); 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt abort_cached = 1; 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmkid && sm->cur_pmksa && 165c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt os_memcmp_const(pmkid, sm->cur_pmksa->pmkid, PMKID_LEN) == 0) { 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: matched PMKID", pmkid, PMKID_LEN); 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_set_pmk_from_pmksa(sm); 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from PMKSA cache", 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmk, sm->pmk_len); 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_notify_cached(sm->eapol); 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->xxkey_len = 0; 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) && sm->eapol) { 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res, pmk_len; 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmk_len = PMK_LEN; 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eapol_sm_get_key(sm->eapol, sm->pmk, PMK_LEN); 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res) { 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-LEAP is an exception from other EAP methods: it 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * uses only 16-byte PMK. 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eapol_sm_get_key(sm->eapol, sm->pmk, 16); 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmk_len = 16; 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 buf[2 * PMK_LEN]; 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eapol_sm_get_key(sm->eapol, buf, 2 * PMK_LEN) == 0) 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->xxkey, buf + PMK_LEN, PMK_LEN); 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->xxkey_len = PMK_LEN; 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(buf, 0, sizeof(buf)); 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == 0) { 19761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct rsn_pmksa_cache_entry *sa = NULL; 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPA: PMK from EAPOL state " 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "machines", sm->pmk, pmk_len); 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmk_len = pmk_len; 201c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt if (sm->proto == WPA_PROTO_RSN && 202c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt !wpa_key_mgmt_ft(sm->key_mgmt)) { 20361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sa = pmksa_cache_add(sm->pmksa, 20461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sm->pmk, pmk_len, 20561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt src_addr, sm->own_addr, 20661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sm->network_ctx, 20761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sm->key_mgmt); 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->cur_pmksa && pmkid && 210c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pmksa_cache_get(sm->pmksa, src_addr, pmkid, NULL)) 211c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt { 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: the new PMK matches with the " 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PMKID"); 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt abort_cached = 0; 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 21861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!sm->cur_pmksa) 21961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sm->cur_pmksa = sa; 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Failed to get master session key from " 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAPOL state machines - key handshake " 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "aborted"); 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->cur_pmksa) { 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: Cancelled PMKSA caching " 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "attempt"); 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->cur_pmksa = NULL; 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt abort_cached = 1; 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (!abort_cached) { 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 237c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt if (abort_cached && wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) && 238f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt !wpa_key_mgmt_ft(sm->key_mgmt) && sm->key_mgmt != WPA_KEY_MGMT_OSEN) 239f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt { 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Send EAPOL-Start to trigger full EAP authentication. */ 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf; 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buflen; 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: no PMKSA entry found - trigger " 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "full EAP authentication"); 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START, 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0, &buflen, NULL); 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf) { 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_ether_send(sm, sm->bssid, ETH_P_EAPOL, 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf, buflen); 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -2; 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_send_2_of_4 - Send message 2 of WPA/RSN 4-Way Handshake 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dst: Destination address for the frame 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key: Pointer to the EAPOL-Key frame header 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ver: Version bits from EAPOL-Key Key Info 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @nonce: Nonce value for the EAPOL-Key frame 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_ie: WPA/RSN IE 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_ie_len: Length of the WPA/RSN IE 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ptk: PTK to use for keyed hash and encryption 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ver, const u8 *nonce, 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *wpa_ie, size_t wpa_ie_len, 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ptk *ptk) 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rlen; 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *reply; 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rbuf; 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rsn_ie_buf = NULL; 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_ie == NULL) { 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No wpa_ie set - " 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "cannot generate msg 2/4"); 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->key_mgmt)) { 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Add PMKR1Name into RSN IE (PMKID-List) and add MDIE and 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * FTIE from (Re)Association Response. 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_ie_buf = os_malloc(wpa_ie_len + 2 + 2 + PMKID_LEN + 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->assoc_resp_ies_len); 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rsn_ie_buf == NULL) 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(rsn_ie_buf, wpa_ie, wpa_ie_len); 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wpa_insert_pmkid(rsn_ie_buf, wpa_ie_len, 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmk_r1_name); 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rsn_ie_buf); 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ie_len += res; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->assoc_resp_ies) { 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(rsn_ie_buf + wpa_ie_len, sm->assoc_resp_ies, 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->assoc_resp_ies_len); 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ie_len += sm->assoc_resp_ies_len; 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ie = rsn_ie_buf; 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len); 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, sizeof(*reply) + wpa_ie_len, 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &rlen, (void *) &reply); 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) { 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rsn_ie_buf); 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 333f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt reply->type = (sm->proto == WPA_PROTO_RSN || 334f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sm->proto == WPA_PROTO_OSEN) ? 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_info, 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC); 338f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_length, 0); 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply->key_length, key->key_length, 2); 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply->replay_counter, key->replay_counter, 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter", reply->replay_counter, 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_data_length, wpa_ie_len); 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply + 1, wpa_ie, wpa_ie_len); 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rsn_ie_buf); 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN); 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/4"); 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL, 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf, rlen, reply->key_mic); 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr, 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ptk *ptk) 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3659866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt size_t ptk_len = wpa_cipher_key_len(sm->pairwise_cipher) + 32; 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->key_mgmt)) 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_derive_ptk_ft(sm, src_addr, key, ptk, ptk_len); 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion", 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->own_addr, sm->bssid, sm->snonce, key->key_nonce, 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) ptk, ptk_len, 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_key_mgmt_sha256(sm->key_mgmt)); 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 38243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt u16 ver, const u8 *key_data, 38343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt size_t key_data_len) 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse ie; 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ptk *ptk; 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 388cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt u8 *kde, *kde_buf = NULL; 389cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt size_t kde_len; 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_get_network_ctx(sm) == NULL) { 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No SSID info " 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "found (msg 1 of 4)"); 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE); 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of 4-Way " 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver); 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&ie, 0, sizeof(ie)); 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 403f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) { 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RSN: msg 1/4 should contain PMKID for the selected PMK */ 40543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", 40643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt key_data, key_data_len); 40743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0) 4081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto failed; 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie.pmkid) { 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: PMKID from " 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Authenticator", ie.pmkid, PMKID_LEN); 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid); 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == -2) { 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: Do not reply to " 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "msg 1/4 - requesting full EAP authentication"); 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res) 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->renew_snonce) { 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) { 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Failed to get random data for SNonce"); 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->renew_snonce = 0; 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce", 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->snonce, WPA_NONCE_LEN); 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Calculate PTK which will be stored as a temporary PTK until it has 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * been verified when processing message 3/4. */ 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ptk = &sm->tptk; 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_derive_ptk(sm, src_addr, key, ptk); 4399866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt if (sm->pairwise_cipher == WPA_CIPHER_TKIP) { 44061593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt u8 buf[8]; 4419866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt /* Supplicant: swap tx/rx Mic keys */ 4429866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt os_memcpy(buf, ptk->u.auth.tx_mic_key, 8); 4439866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt os_memcpy(ptk->u.auth.tx_mic_key, ptk->u.auth.rx_mic_key, 8); 4449866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt os_memcpy(ptk->u.auth.rx_mic_key, buf, 8); 44561593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt os_memset(buf, 0, sizeof(buf)); 4469866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt } 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->tptk_set = 1; 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 449cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt kde = sm->assoc_wpa_ie; 450cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt kde_len = sm->assoc_wpa_ie_len; 451cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 452cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_P2P 453cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (sm->p2p) { 454cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt kde_buf = os_malloc(kde_len + 2 + RSN_SELECTOR_LEN + 1); 455cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (kde_buf) { 456cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt u8 *pos; 457cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_DEBUG, "P2P: Add IP Address Request KDE " 458cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt "into EAPOL-Key 2/4"); 459cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt os_memcpy(kde_buf, kde, kde_len); 460cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt kde = kde_buf; 461cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt pos = kde + kde_len; 462cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt *pos++ = WLAN_EID_VENDOR_SPECIFIC; 463cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt *pos++ = RSN_SELECTOR_LEN + 1; 464cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt RSN_SELECTOR_PUT(pos, WFA_KEY_DATA_IP_ADDR_REQ); 465cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt pos += RSN_SELECTOR_LEN; 466cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt *pos++ = 0x01; 467cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt kde_len = pos - kde; 468cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 469cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 470cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_P2P */ 471cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, sm->snonce, 473cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt kde, kde_len, ptk)) 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 476cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt os_free(kde_buf); 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->anonce, key->key_nonce, WPA_NONCE_LEN); 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfailed: 481cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt os_free(kde_buf); 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_sm_start_preauth(void *eloop_ctx, void *timeout_ctx) 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm = eloop_ctx; 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_candidate_process(sm); 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_key_neg_complete(struct wpa_sm *sm, 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, int secure) 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Key negotiation completed with " 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " [PTK=%s GTK=%s]", MAC2STR(addr), 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_cipher_txt(sm->pairwise_cipher), 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_cipher_txt(sm->group_cipher)); 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_cancel_auth_timeout(sm); 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_set_state(sm, WPA_COMPLETED); 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (secure) { 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_mlme_setprotection( 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, addr, MLME_SETPROTECTION_PROTECT_TYPE_RX_TX, 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_notify_portValid(sm->eapol, TRUE); 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_wpa_psk(sm->key_mgmt)) 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_notify_eap_success(sm->eapol, TRUE); 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Start preauthentication after a short wait to avoid a 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * possible race condition between the data receive and key 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * configuration after the 4-Way Handshake. This increases the 5151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * likelihood of the first preauth EAPOL-Start frame getting to 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the target AP. 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(1, 0, wpa_sm_start_preauth, sm, NULL); 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->cur_pmksa && sm->cur_pmksa->opportunistic) { 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: Authenticator accepted " 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "opportunistic PMKSA entry - marking it valid"); 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->cur_pmksa->opportunistic = 0; 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->key_mgmt)) { 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Prepare for the next transition */ 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ft_prepare_auth_request(sm, NULL); 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_sm_rekey_ptk(void *eloop_ctx, void *timeout_ctx) 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm = eloop_ctx; 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Request PTK rekeying"); 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_key_request(sm, 0, 1); 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_install_ptk(struct wpa_sm *sm, 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key) 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int keylen, rsclen; 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wpa_alg alg; 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *key_rsc; 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Installing PTK to the driver"); 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (sm->pairwise_cipher == WPA_CIPHER_NONE) { 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Pairwise Cipher " 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Suite: NONE - do not use pairwise keys"); 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 5614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 5624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) { 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Unsupported pairwise cipher %d", 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pairwise_cipher); 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt alg = wpa_cipher_to_alg(sm->pairwise_cipher); 5704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt keylen = wpa_cipher_key_len(sm->pairwise_cipher); 5714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt rsclen = wpa_cipher_rsc_len(sm->pairwise_cipher); 5724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 573f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) { 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_rsc = null_rsc; 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_rsc = key->key_rsc; 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, rsclen); 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_set_key(sm, alg, sm->bssid, 0, 1, key_rsc, rsclen, 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) sm->ptk.tk1, keylen) < 0) { 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Failed to set PTK to the " 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "driver (alg=%d keylen=%d bssid=" MACSTR ")", 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt alg, keylen, MAC2STR(sm->bssid)); 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_ptk_rekey) { 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL); 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(sm->wpa_ptk_rekey, 0, wpa_sm_rekey_ptk, 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, NULL); 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_check_group_cipher(struct wpa_sm *sm, 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int group_cipher, 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int keylen, int maxkeylen, 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int *key_rsc_len, 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wpa_alg *alg) 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt int klen; 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt *alg = wpa_cipher_to_alg(group_cipher); 6084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (*alg == WPA_ALG_NONE) { 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Unsupported Group Cipher %d", 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group_cipher); 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt *key_rsc_len = wpa_cipher_rsc_len(group_cipher); 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt klen = wpa_cipher_key_len(group_cipher); 6174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (keylen != klen || maxkeylen < klen) { 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Unsupported %s Group Cipher key length %d (%d)", 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_cipher_txt(group_cipher), keylen, maxkeylen); 6214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return -1; 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_gtk_data { 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wpa_alg alg; 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tx, key_rsc_len, keyidx; 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 gtk[32]; 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int gtk_len; 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_install_gtk(struct wpa_sm *sm, 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_gtk_data *gd, 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *key_rsc) 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *_gtk = gd->gtk; 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 gtk_buf[32]; 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPA: Group Key", gd->gtk, gd->gtk_len); 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Installing GTK to the driver (keyidx=%d tx=%d len=%d)", 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd->keyidx, gd->tx, gd->gtk_len); 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, gd->key_rsc_len); 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->group_cipher == WPA_CIPHER_TKIP) { 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Swap Tx/Rx keys for Michael MIC */ 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(gtk_buf, gd->gtk, 16); 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(gtk_buf + 16, gd->gtk + 24, 8); 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(gtk_buf + 24, gd->gtk + 16, 8); 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _gtk = gtk_buf; 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pairwise_cipher == WPA_CIPHER_NONE) { 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_set_key(sm, gd->alg, NULL, 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd->keyidx, 1, key_rsc, gd->key_rsc_len, 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _gtk, gd->gtk_len) < 0) { 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Failed to set GTK to the driver " 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(Group only)"); 66161593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt os_memset(gtk_buf, 0, sizeof(gtk_buf)); 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (wpa_sm_set_key(sm, gd->alg, broadcast_ether_addr, 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd->keyidx, gd->tx, key_rsc, gd->key_rsc_len, 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _gtk, gd->gtk_len) < 0) { 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Failed to set GTK to " 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the driver (alg=%d keylen=%d keyidx=%d)", 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd->alg, gd->gtk_len, gd->keyidx); 67161593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt os_memset(gtk_buf, 0, sizeof(gtk_buf)); 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 67461593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt os_memset(gtk_buf, 0, sizeof(gtk_buf)); 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_gtk_tx_bit_workaround(const struct wpa_sm *sm, 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tx) 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tx && sm->pairwise_cipher != WPA_CIPHER_NONE) { 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Ignore Tx bit for GTK if a pairwise key is used. One AP 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * seemed to set this bit (incorrectly, since Tx is only when 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * doing Group Key only APs) and without this workaround, the 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * data connection does not work because wpa_supplicant 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * configured non-zero keyidx to be used for unicast. */ 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Tx bit set for GTK, but pairwise " 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "keys are used - ignore Tx bit"); 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return tx; 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm, 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *gtk, size_t gtk_len, 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int key_info) 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_gtk_data gd; 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames - Figure 43x 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * GTK KDE format: 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * KeyID[bits 0-1], Tx [bit 2], Reserved [bits 3-7] 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Reserved [bits 0-7] 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * GTK 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&gd, 0, sizeof(gd)); 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "RSN: received GTK in pairwise handshake", 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gtk, gtk_len); 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gtk_len < 2 || gtk_len - 2 > sizeof(gd.gtk)) 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd.keyidx = gtk[0] & 0x3; 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd.tx = wpa_supplicant_gtk_tx_bit_workaround(sm, 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !!(gtk[0] & BIT(2))); 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gtk += 2; 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gtk_len -= 2; 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(gd.gtk, gtk, gtk_len); 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd.gtk_len = gtk_len; 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 729fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (sm->group_cipher != WPA_CIPHER_GTK_NOT_USED && 730fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt (wpa_supplicant_check_group_cipher(sm, sm->group_cipher, 731fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt gtk_len, gtk_len, 732fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt &gd.key_rsc_len, &gd.alg) || 733fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_supplicant_install_gtk(sm, &gd, key->key_rsc))) { 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: Failed to install GTK"); 73661593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt os_memset(&gd, 0, sizeof(gd)); 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 73961593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt os_memset(&gd, 0, sizeof(gd)); 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_key_neg_complete(sm, sm->bssid, 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info & WPA_KEY_INFO_SECURE); 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee80211w_set_keys(struct wpa_sm *sm, 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *ie) 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 751b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (!wpa_cipher_valid_mgmt_group(sm->mgmt_group_cipher)) 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie->igtk) { 755b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt size_t len; 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_igtk_kde *igtk; 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 keyidx; 758b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt len = wpa_cipher_key_len(sm->mgmt_group_cipher); 759b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (ie->igtk_len != WPA_IGTK_KDE_PREFIX_LEN + len) 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt igtk = (const struct wpa_igtk_kde *) ie->igtk; 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keyidx = WPA_GET_LE16(igtk->keyid); 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: IGTK keyid %d " 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pn %02x%02x%02x%02x%02x%02x", 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keyidx, MAC2STR(igtk->pn)); 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK", 767b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt igtk->igtk, len); 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keyidx > 4095) { 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Invalid IGTK KeyID %d", keyidx); 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 773b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher), 774b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt broadcast_ether_addr, 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keyidx, 0, igtk->pn, sizeof(igtk->pn), 776b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt igtk->igtk, len) < 0) { 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Failed to configure IGTK to the driver"); 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_IEEE80211W */ 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_report_ie_mismatch(struct wpa_sm *sm, 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *reason, const u8 *src_addr, 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *wpa_ie, size_t wpa_ie_len, 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *rsn_ie, size_t rsn_ie_len) 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: %s (src=" MACSTR ")", 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reason, MAC2STR(src_addr)); 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->ap_wpa_ie) { 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_INFO, "WPA: WPA IE in Beacon/ProbeResp", 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ap_wpa_ie, sm->ap_wpa_ie_len); 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_ie) { 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->ap_wpa_ie) { 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: No WPA IE in Beacon/ProbeResp"); 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_INFO, "WPA: WPA IE in 3/4 msg", 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ie, wpa_ie_len); 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->ap_rsn_ie) { 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_INFO, "WPA: RSN IE in Beacon/ProbeResp", 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ap_rsn_ie, sm->ap_rsn_ie_len); 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rsn_ie) { 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->ap_rsn_ie) { 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: No RSN IE in Beacon/ProbeResp"); 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_INFO, "WPA: RSN IE in 3/4 msg", 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_ie, rsn_ie_len); 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 824d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_sm_deauthenticate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS); 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ft_validate_mdie(struct wpa_sm *sm, 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *ie, 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *assoc_resp_mdie) 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_mdie *mdie; 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mdie = (struct rsn_mdie *) (ie->mdie + 2); 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie->mdie == NULL || ie->mdie_len < 2 + sizeof(*mdie) || 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(mdie->mobility_domain, sm->mobility_domain, 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MOBILITY_DOMAIN_ID_LEN) != 0) { 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: MDIE in msg 3/4 did " 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not match with the current mobility domain"); 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (assoc_resp_mdie && 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (assoc_resp_mdie[1] != ie->mdie[1] || 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(assoc_resp_mdie, ie->mdie, 2 + ie->mdie[1]) != 0)) { 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: MDIE mismatch"); 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: MDIE in EAPOL-Key msg 3/4", 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->mdie, 2 + ie->mdie[1]); 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: MDIE in (Re)Association Response", 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt assoc_resp_mdie, 2 + assoc_resp_mdie[1]); 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ft_validate_ftie(struct wpa_sm *sm, 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *ie, 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *assoc_resp_ftie) 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie->ftie == NULL) { 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FT: No FTIE in EAPOL-Key msg 3/4"); 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (assoc_resp_ftie == NULL) 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (assoc_resp_ftie[1] != ie->ftie[1] || 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(assoc_resp_ftie, ie->ftie, 2 + ie->ftie[1]) != 0) { 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: FTIE mismatch"); 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 3/4", 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->ftie, 2 + ie->ftie[1]); 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)Association Response", 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt assoc_resp_ftie, 2 + assoc_resp_ftie[1]); 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ft_validate_rsnie(struct wpa_sm *sm, 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *ie) 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data rsn; 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ie->rsn_ie) 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Verify that PMKR1Name from EAPOL-Key message 3/4 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * matches with the value we derived. 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_parse_wpa_ie_rsn(ie->rsn_ie, ie->rsn_ie_len, &rsn) < 0 || 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn.num_pmkid != 1 || rsn.pmkid == NULL) { 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: No PMKR1Name in " 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FT 4-way handshake message 3/4"); 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 909c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(rsn.pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0) 910c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt { 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FT: PMKR1Name mismatch in " 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FT 4-way handshake message 3/4"); 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Authenticator", 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn.pmkid, WPA_PMK_NAME_LEN); 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name", 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmk_r1_name, WPA_PMK_NAME_LEN); 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_validate_ie_ft(struct wpa_sm *sm, 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *ie) 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end, *mdie = NULL, *ftie = NULL; 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->assoc_resp_ies) { 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = sm->assoc_resp_ies; 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + sm->assoc_resp_ies_len; 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos + 2 < end) { 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + 2 + pos[1] > end) 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (*pos) { 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WLAN_EID_MOBILITY_DOMAIN: 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mdie = pos; 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WLAN_EID_FAST_BSS_TRANSITION: 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = pos; 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + pos[1]; 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ft_validate_mdie(sm, src_addr, ie, mdie) < 0 || 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ft_validate_ftie(sm, src_addr, ie, ftie) < 0 || 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ft_validate_rsnie(sm, src_addr, ie) < 0) 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_validate_ie(struct wpa_sm *sm, 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *ie) 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->ap_wpa_ie == NULL && sm->ap_rsn_ie == NULL) { 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: No WPA/RSN IE for this AP known. " 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Trying to get from scan results"); 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_get_beacon_ie(sm) < 0) { 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Could not find AP from " 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the scan results"); 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Found the current AP from " 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "updated scan results"); 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie->wpa_ie == NULL && ie->rsn_ie == NULL && 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (sm->ap_wpa_ie || sm->ap_rsn_ie)) { 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match " 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "with IE in Beacon/ProbeResp (no IE?)", 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt src_addr, ie->wpa_ie, ie->wpa_ie_len, 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->rsn_ie, ie->rsn_ie_len); 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((ie->wpa_ie && sm->ap_wpa_ie && 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (ie->wpa_ie_len != sm->ap_wpa_ie_len || 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(ie->wpa_ie, sm->ap_wpa_ie, ie->wpa_ie_len) != 0)) || 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (ie->rsn_ie && sm->ap_rsn_ie && 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_compare_rsn_ie(wpa_key_mgmt_ft(sm->key_mgmt), 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ap_rsn_ie, sm->ap_rsn_ie_len, 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->rsn_ie, ie->rsn_ie_len))) { 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match " 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "with IE in Beacon/ProbeResp", 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt src_addr, ie->wpa_ie, ie->wpa_ie_len, 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->rsn_ie, ie->rsn_ie_len); 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->proto == WPA_PROTO_WPA && 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->rsn_ie && sm->ap_rsn_ie == NULL && sm->rsn_enabled) { 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_report_ie_mismatch(sm, "Possible downgrade attack " 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "detected - RSN was enabled and RSN IE " 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "was in msg 3/4, but not in " 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Beacon/ProbeResp", 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt src_addr, ie->wpa_ie, ie->wpa_ie_len, 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->rsn_ie, ie->rsn_ie_len); 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->key_mgmt) && 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_validate_ie_ft(sm, src_addr, ie) < 0) 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_send_4_of_4 - Send message 4 of WPA/RSN 4-Way Handshake 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dst: Destination address for the frame 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key: Pointer to the EAPOL-Key frame header 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ver: Version bits from EAPOL-Key Key Info 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key_info: Key Info 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ptk: PTK to use for keyed hash and encryption 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst, 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 ver, u16 key_info, 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ptk *ptk) 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rlen; 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *reply; 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rbuf; 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, 104321de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt sizeof(*reply), &rlen, (void *) &reply); 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1047f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt reply->type = (sm->proto == WPA_PROTO_RSN || 1048f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sm->proto == WPA_PROTO_OSEN) ? 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info &= WPA_KEY_INFO_SECURE; 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info |= ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC; 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_info, key_info); 1053f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_length, 0); 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply->key_length, key->key_length, 2); 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply->replay_counter, key->replay_counter, 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 106021de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt WPA_PUT_BE16(reply->key_data_length, 0); 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 4/4"); 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL, 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf, rlen, reply->key_mic); 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 107243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt u16 ver, const u8 *key_data, 107343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt size_t key_data_len) 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 107543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt u16 key_info, keylen; 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse ie; 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE); 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 3 of 4-Way " 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Handshake from " MACSTR " (ver=%d)", MAC2STR(sm->bssid), ver); 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = WPA_GET_BE16(key->key_info); 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 108443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", key_data, key_data_len); 108543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0) 10861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto failed; 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: GTK IE in unencrypted key data"); 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie.igtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: IGTK KDE in unencrypted key data"); 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1099b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (ie.igtk && 1100b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt wpa_cipher_valid_mgmt_group(sm->mgmt_group_cipher) && 1101b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt ie.igtk_len != WPA_IGTK_KDE_PREFIX_LEN + 1102b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt (unsigned int) wpa_cipher_key_len(sm->mgmt_group_cipher)) { 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Invalid IGTK KDE length %lu", 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) ie.igtk_len); 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0) 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) { 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: ANonce from message 1 of 4-Way Handshake " 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "differs from 3 of 4-Way Handshake - drop packet (src=" 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR ")", MAC2STR(sm->bssid)); 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keylen = WPA_GET_BE16(key->key_length); 11224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (keylen != wpa_cipher_key_len(sm->pairwise_cipher)) { 11234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 11244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt "WPA: Invalid %s key length %d (src=" MACSTR 11254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt ")", wpa_cipher_txt(sm->pairwise_cipher), keylen, 11264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt MAC2STR(sm->bssid)); 11274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt goto failed; 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1130cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_P2P 1131cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (ie.ip_addr_alloc) { 1132cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt os_memcpy(sm->p2p_ip_addr, ie.ip_addr_alloc, 3 * 4); 1133cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_hexdump(MSG_DEBUG, "P2P: IP address info", 1134cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt sm->p2p_ip_addr, sizeof(sm->p2p_ip_addr)); 1135cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 1136cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_P2P */ 1137cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info, 113921de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt &sm->ptk)) { 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SNonce was successfully used in msg 3/4, so mark it to be renewed 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * for the next 4-Way Handshake. If msg 3 is received again, the old 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SNonce will still be used to avoid changing PTK. */ 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->renew_snonce = 1; 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_INSTALL) { 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_install_ptk(sm, key)) 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_SECURE) { 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_mlme_setprotection( 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, sm->bssid, MLME_SETPROTECTION_PROTECT_TYPE_RX, 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_notify_portValid(sm->eapol, TRUE); 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE); 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1161fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (sm->group_cipher == WPA_CIPHER_GTK_NOT_USED) { 1162fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_supplicant_key_neg_complete(sm, sm->bssid, 1163fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt key_info & WPA_KEY_INFO_SECURE); 1164fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } else if (ie.gtk && 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_pairwise_gtk(sm, key, 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie.gtk, ie.gtk_len, key_info) < 0) { 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: Failed to configure GTK"); 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ieee80211w_set_keys(sm, &ie) < 0) { 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: Failed to configure IGTK"); 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1178cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (ie.gtk) 1179cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_sm_set_rekey_offload(sm); 11801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfailed: 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm, 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *keydata, 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t keydatalen, 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info, 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_gtk_data *gd) 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int maxkeylen; 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse ie; 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: msg 1/2 key data", keydata, keydatalen); 11981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_supplicant_parse_ies(keydata, keydatalen, &ie) < 0) 11991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { 12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: GTK IE in unencrypted key data"); 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie.gtk == NULL) { 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: No GTK IE in Group Key msg 1/2"); 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt maxkeylen = gd->gtk_len = ie.gtk_len - 2; 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher, 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd->gtk_len, maxkeylen, 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &gd->key_rsc_len, &gd->alg)) 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: received GTK in group key handshake", 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie.gtk, ie.gtk_len); 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd->keyidx = ie.gtk[0] & 0x3; 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd->tx = wpa_supplicant_gtk_tx_bit_workaround(sm, 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !!(ie.gtk[0] & BIT(2))); 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie.gtk_len - 2 > sizeof(gd->gtk)) { 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: Too long GTK in GTK IE (len=%lu)", 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) ie.gtk_len - 2); 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(gd->gtk, ie.gtk + 2, ie.gtk_len - 2); 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ieee80211w_set_keys(sm, &ie) < 0) 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: Failed to configure IGTK"); 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm, 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 124043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt const u8 *key_data, 124143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt size_t key_data_len, u16 key_info, 124243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt u16 ver, struct wpa_gtk_data *gd) 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t maxkeylen; 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd->gtk_len = WPA_GET_BE16(key->key_length); 124743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt maxkeylen = key_data_len; 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (maxkeylen < 8) { 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Too short maxkeylen (%lu)", 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) maxkeylen); 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt maxkeylen -= 8; 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher, 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd->gtk_len, maxkeylen, 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &gd->key_rsc_len, &gd->alg)) 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd->keyidx = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >> 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_KEY_INDEX_SHIFT; 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) { 126661593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt u8 ek[32]; 126743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt if (key_data_len > sizeof(gd->gtk)) { 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: RC4 key data too long (%lu)", 127043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt (unsigned long) key_data_len); 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 127361593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt os_memcpy(ek, key->key_iv, 16); 127461593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt os_memcpy(ek + 16, sm->ptk.kek, 16); 127543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt os_memcpy(gd->gtk, key_data, key_data_len); 127643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt if (rc4_skip(ek, 32, 256, gd->gtk, key_data_len)) { 127761593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt os_memset(ek, 0, sizeof(ek)); 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, 12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: RC4 failed"); 12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 128261593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt os_memset(ek, 0, sizeof(ek)); 12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { 128443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt if (maxkeylen % 8) { 12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Unsupported AES-WRAP len %lu", 128743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt (unsigned long) maxkeylen); 12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (maxkeylen > sizeof(gd->gtk)) { 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: AES-WRAP key data " 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "too long (keydatalen=%lu maxkeylen=%lu)", 129443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt (unsigned long) key_data_len, 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) maxkeylen); 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12989ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt if (aes_unwrap(sm->ptk.kek, 16, maxkeylen / 8, key_data, 12999ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt gd->gtk)) { 13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: AES unwrap failed - could not decrypt " 13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "GTK"); 13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Unsupported key_info type %d", ver); 13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd->tx = wpa_supplicant_gtk_tx_bit_workaround( 13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, !!(key_info & WPA_KEY_INFO_TXRX)); 13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_send_2_of_2(struct wpa_sm *sm, 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ver, u16 key_info) 13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rlen; 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *reply; 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rbuf; 13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, 13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(*reply), &rlen, (void *) &reply); 13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) 13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1329f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt reply->type = (sm->proto == WPA_PROTO_RSN || 1330f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sm->proto == WPA_PROTO_OSEN) ? 13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; 13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info &= WPA_KEY_INFO_KEY_INDEX_MASK; 13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info |= ver | WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE; 13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_info, key_info); 1335f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) 13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_length, 0); 13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply->key_length, key->key_length, 2); 13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply->replay_counter, key->replay_counter, 13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_data_length, 0); 13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/2"); 13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_send(sm, sm->ptk.kck, ver, sm->bssid, ETH_P_EAPOL, 13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf, rlen, reply->key_mic); 13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_1_of_2(struct wpa_sm *sm, 13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, 13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 135543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt const u8 *key_data, 135643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt size_t key_data_len, u16 ver) 13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 135843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt u16 key_info; 13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int rekey, ret; 13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_gtk_data gd; 13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&gd, 0, sizeof(gd)); 13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rekey = wpa_sm_get_state(sm) == WPA_COMPLETED; 13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of Group Key " 13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver); 13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = WPA_GET_BE16(key->key_info); 13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1370f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) { 137143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt ret = wpa_supplicant_process_1_of_2_rsn(sm, key_data, 137243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt key_data_len, key_info, 13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &gd); 13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 137543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt ret = wpa_supplicant_process_1_of_2_wpa(sm, key, key_data, 137643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt key_data_len, 137743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt key_info, ver, &gd); 13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE); 13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_install_gtk(sm, &gd, key->key_rsc) || 13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_send_2_of_2(sm, key, ver, key_info)) 13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rekey) { 13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Group rekeying " 13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "completed with " MACSTR " [GTK=%s]", 13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(sm->bssid), wpa_cipher_txt(sm->group_cipher)); 13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_cancel_auth_timeout(sm); 13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_set_state(sm, WPA_COMPLETED); 13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_key_neg_complete(sm, sm->bssid, 13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info & 13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_SECURE); 13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1400cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 1401cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_sm_set_rekey_offload(sm); 1402cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfailed: 14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); 14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm, 14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *key, 14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 ver, 14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mic[16]; 14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ok = 0; 14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(mic, key->key_mic, 16); 14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->tptk_set) { 14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(key->key_mic, 0, 16); 14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_mic(sm->tptk.kck, ver, buf, len, 14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_mic); 1423c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(mic, key->key_mic, 16) != 0) { 14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Invalid EAPOL-Key MIC " 14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "when using TPTK - ignoring TPTK"); 14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ok = 1; 14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->tptk_set = 0; 14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ptk_set = 1; 14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk)); 143261593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt os_memset(&sm->tptk, 0, sizeof(sm->tptk)); 14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ok && sm->ptk_set) { 14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(key->key_mic, 0, 16); 14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_mic(sm->ptk.kck, ver, buf, len, 14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_mic); 1440c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(mic, key->key_mic, 16) != 0) { 14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Invalid EAPOL-Key MIC - " 14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dropping packet"); 14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ok = 1; 14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ok) { 14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Could not verify EAPOL-Key MIC - " 14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dropping packet"); 14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->rx_replay_counter, key->replay_counter, 14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->rx_replay_counter_set = 1; 14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */ 14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm, 146543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt struct wpa_eapol_key *key, u16 ver, 146643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt u8 *key_data, size_t *key_data_len) 14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data", 146943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt key_data, *key_data_len); 14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->ptk_set) { 14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: PTK not available, cannot decrypt EAPOL-Key Key " 14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Data"); 14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Decrypt key data here so that this operation does not need 14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to be implemented separately for each message type. */ 14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) { 14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ek[32]; 14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ek, key->key_iv, 16); 14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ek + 16, sm->ptk.kek, 16); 148343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt if (rc4_skip(ek, 32, 256, key_data, *key_data_len)) { 148461593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt os_memset(ek, 0, sizeof(ek)); 14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, 14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: RC4 failed"); 14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 148961593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt os_memset(ek, 0, sizeof(ek)); 14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || 1491f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ver == WPA_KEY_INFO_TYPE_AES_128_CMAC || 1492f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sm->key_mgmt == WPA_KEY_MGMT_OSEN) { 14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf; 149443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt if (*key_data_len < 8 || *key_data_len % 8) { 14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 149643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt "WPA: Unsupported AES-WRAP len %u", 149743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt (unsigned int) *key_data_len); 14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 150043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt *key_data_len -= 8; /* AES-WRAP adds 8 bytes */ 150143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt buf = os_malloc(*key_data_len); 15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: No memory for AES-UNWRAP buffer"); 15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15079ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt if (aes_unwrap(sm->ptk.kek, 16, *key_data_len / 8, 150843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt key_data, buf)) { 15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: AES unwrap failed - " 15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "could not decrypt EAPOL-Key key data"); 15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 151543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt os_memcpy(key_data, buf, *key_data_len); 15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 151743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt WPA_PUT_BE16(key->key_data_length, *key_data_len); 15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Unsupported key_info type %d", ver); 15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPA: decrypted EAPOL-Key key data", 152443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt key_data, *key_data_len); 15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_aborted_cached - Notify WPA that PMKSA caching was aborted 15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_aborted_cached(struct wpa_sm *sm) 15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm && sm->cur_pmksa) { 15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: Cancelling PMKSA caching attempt"); 15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->cur_pmksa = NULL; 15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_eapol_key_dump(struct wpa_sm *sm, 15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key) 15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_STDOUT_DEBUG 15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info = WPA_GET_BE16(key->key_info); 15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, " EAPOL-Key type=%d", key->type); 15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " key_info 0x%x (ver=%d keyidx=%d rsvd=%d %s%s%s%s%s%s%s%s)", 15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info, key_info & WPA_KEY_INFO_TYPE_MASK, 15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >> 15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_KEY_INDEX_SHIFT, 15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (key_info & (BIT(13) | BIT(14) | BIT(15))) >> 13, 15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info & WPA_KEY_INFO_KEY_TYPE ? "Pairwise" : "Group", 15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info & WPA_KEY_INFO_INSTALL ? " Install" : "", 15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info & WPA_KEY_INFO_ACK ? " Ack" : "", 15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info & WPA_KEY_INFO_MIC ? " MIC" : "", 15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info & WPA_KEY_INFO_SECURE ? " Secure" : "", 15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info & WPA_KEY_INFO_ERROR ? " Error" : "", 15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info & WPA_KEY_INFO_REQUEST ? " Request" : "", 15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info & WPA_KEY_INFO_ENCR_KEY_DATA ? " Encr" : ""); 15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " key_length=%u key_data_length=%u", 15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_BE16(key->key_length), 15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_BE16(key->key_data_length)); 15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, " replay_counter", 15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->replay_counter, WPA_REPLAY_COUNTER_LEN); 15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, " key_nonce", key->key_nonce, WPA_NONCE_LEN); 15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, " key_iv", key->key_iv, 16); 15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, " key_rsc", key->key_rsc, 8); 15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, " key_id (reserved)", key->key_id, 8); 15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, " key_mic", key->key_mic, 16); 15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_STDOUT_DEBUG */ 15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_rx_eapol - Process received WPA EAPOL frames 15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @src_addr: Source MAC address of the EAPOL packet 15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Pointer to the beginning of the EAPOL data (EAPOL header) 15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Length of the EAPOL frame 15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 = WPA EAPOL-Key processed, 0 = not a WPA EAPOL-Key, -1 failure 15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called for each received EAPOL frame. Other than EAPOL-Key 15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * frames can be skipped if filtering is done elsewhere. wpa_sm_rx_eapol() is 15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * only processing WPA and WPA2 EAPOL-Key frames. 15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The received EAPOL-Key packets are validated and valid packets are replied 15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to. In addition, key material (PTK, GTK) is configured at the end of a 15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * successful key handshake. 15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, 15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 159843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt size_t plen, data_len, key_data_len; 159943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt const struct ieee802_1x_hdr *hdr; 16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *key; 16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info, ver; 160243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt u8 *tmp = NULL; 16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = -1; 16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey = NULL; 160543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt u8 *key_data; 16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ft_completed = 0; 16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < sizeof(*hdr) + sizeof(*key)) { 16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: EAPOL frame too short to be a WPA " 16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAPOL-Key (len %lu, expecting at least %lu)", 16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len, 16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) sizeof(*hdr) + sizeof(*key)); 16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 162043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt hdr = (const struct ieee802_1x_hdr *) buf; 16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = be_to_host16(hdr->length); 16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data_len = plen + sizeof(*hdr); 16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "IEEE 802.1X RX: version=%d type=%d length=%lu", 16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->version, hdr->type, (unsigned long) plen); 16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr->version < EAPOL_VERSION) { 16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: backwards compatibility */ 16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr->type != IEEE802_1X_TYPE_EAPOL_KEY) { 16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: EAPOL frame (type %u) discarded, " 16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not a Key frame", hdr->type); 16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 163743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL-Key", buf, len); 16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (plen > len - sizeof(*hdr) || plen < sizeof(*key)) { 16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: EAPOL frame payload size %lu " 16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "invalid (frame size %lu)", 16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) plen, (unsigned long) len); 16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 164643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt if (data_len < len) { 164743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 164843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt "WPA: ignoring %lu bytes after the IEEE 802.1X data", 164943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt (unsigned long) len - data_len); 165043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt } 165143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt 165243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt /* 165343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt * Make a copy of the frame since we need to modify the buffer during 165443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt * MAC validation and Key Data decryption. 165543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt */ 165643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt tmp = os_malloc(data_len); 165743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt if (tmp == NULL) 165843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt goto out; 165943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt os_memcpy(tmp, buf, data_len); 166043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt key = (struct wpa_eapol_key *) (tmp + sizeof(struct ieee802_1x_hdr)); 166143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt key_data = (u8 *) (key + 1); 16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN) 16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: EAPOL-Key type (%d) unknown, discarded", 16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->type); 16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_dump(sm, key); 16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 167343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt key_data_len = WPA_GET_BE16(key->key_data_length); 167443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt if (key_data_len > plen - sizeof(struct wpa_eapol_key)) { 167543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Invalid EAPOL-Key " 167643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt "frame - key_data overflow (%u > %u)", 167743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt (unsigned int) key_data_len, 167843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt (unsigned int) (plen - sizeof(struct wpa_eapol_key))); 167943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt goto out; 16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 168143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt 168243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt eapol_sm_notify_lower_layer_success(sm->eapol, 0); 16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = WPA_GET_BE16(key->key_info); 16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = key_info & WPA_KEY_INFO_TYPE_MASK; 16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && 16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W) 16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver != WPA_KEY_INFO_TYPE_AES_128_CMAC && 16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */ 1689f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES && 1690f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sm->key_mgmt != WPA_KEY_MGMT_OSEN) { 16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Unsupported EAPOL-Key descriptor version %d", 16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver); 16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1697f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (sm->key_mgmt == WPA_KEY_MGMT_OSEN && 1698f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) { 1699f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 1700f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt "OSEN: Unsupported EAPOL-Key descriptor version %d", 1701f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ver); 1702f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt goto out; 1703f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1704f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->key_mgmt)) { 17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* IEEE 802.11r uses a new key_info type (AES-128-CMAC). */ 17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { 17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FT: AP did not use AES-128-CMAC"); 17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_sha256(sm->key_mgmt)) { 1717f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC && 1718f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sm->key_mgmt != WPA_KEY_MGMT_OSEN) { 17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: AP did not use the " 17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "negotiated AES-128-CMAC"); 17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pairwise_cipher == WPA_CIPHER_CCMP && 17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { 17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: CCMP is used, but EAPOL-Key " 17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "descriptor version (%d) is not 2", ver); 17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->group_cipher != WPA_CIPHER_CCMP && 17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(key_info & WPA_KEY_INFO_KEY_TYPE)) { 17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Earlier versions of IEEE 802.11i did not explicitly 17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * require version 2 descriptor for all EAPOL-Key 17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * packets, so allow group keys to use version 1 if 17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * CCMP is not used for them. */ 17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Backwards compatibility: allow invalid " 17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "version for non-CCMP group keys"); 1740658fb4adb9458c3055c64a43833f1a9e89b4db74Jouni Malinen } else if (ver == WPA_KEY_INFO_TYPE_AES_128_CMAC) { 1741658fb4adb9458c3055c64a43833f1a9e89b4db74Jouni Malinen wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 1742658fb4adb9458c3055c64a43833f1a9e89b4db74Jouni Malinen "WPA: Interoperability workaround: allow incorrect (should have been HMAC-SHA1), but stronger (is AES-128-CMAC), descriptor version to be used"); 17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 1745717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt } else if (sm->pairwise_cipher == WPA_CIPHER_GCMP && 1746717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { 174761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 174861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "WPA: GCMP is used, but EAPOL-Key " 174961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "descriptor version (%d) is not 2", ver); 175061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt goto out; 175161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { 17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peerkey->addr, src_addr, ETH_ALEN) == 0) 17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(key_info & WPA_KEY_INFO_SMK_MESSAGE) && peerkey) { 17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!peerkey->initiator && peerkey->replay_counter_set && 17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(key->replay_counter, peerkey->replay_counter, 17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN) <= 0) { 17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: EAPOL-Key Replay Counter did not " 17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "increase (STK) - dropping packet"); 17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (peerkey->initiator) { 17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 _tmp[WPA_REPLAY_COUNTER_LEN]; 17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(_tmp, key->replay_counter, 17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(_tmp, WPA_REPLAY_COUNTER_LEN); 17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(_tmp, peerkey->replay_counter, 17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN) != 0) { 17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: EAPOL-Key Replay " 17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Counter did not match (STK) - " 17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dropping packet"); 17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey && peerkey->initiator && (key_info & WPA_KEY_INFO_ACK)) { 17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: Ack bit in key_info from STK peer"); 17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!peerkey && sm->rx_replay_counter_set && 17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(key->replay_counter, sm->rx_replay_counter, 17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN) <= 0) { 17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: EAPOL-Key Replay Counter did not increase - " 17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dropping packet"); 17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(key_info & (WPA_KEY_INFO_ACK | WPA_KEY_INFO_SMK_MESSAGE)) 18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt && (peerkey == NULL || !peerkey->initiator) 18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ) { 18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: No Ack bit in key_info"); 18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_REQUEST) { 18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: EAPOL-Key with Request bit - dropped"); 18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((key_info & WPA_KEY_INFO_MIC) && !peerkey && 18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_verify_eapol_key_mic(sm, key, ver, tmp, data_len)) 18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((key_info & WPA_KEY_INFO_MIC) && peerkey && 18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey_verify_eapol_key_mic(sm, peerkey, key, ver, tmp, data_len)) 18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1825f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if ((sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) && 18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { 182743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt if (wpa_supplicant_decrypt_key_data(sm, key, ver, key_data, 182843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt &key_data_len)) 18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_KEY_TYPE) { 18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) { 18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Ignored EAPOL-Key (Pairwise) with " 18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "non-zero key index"); 18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey) { 18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* PeerKey 4-Way Handshake */ 1841c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt peerkey_rx_eapol_4way(sm, peerkey, key, key_info, ver, 1842c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt key_data, key_data_len); 18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_info & WPA_KEY_INFO_MIC) { 18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3/4 4-Way Handshake */ 184543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt wpa_supplicant_process_3_of_4(sm, key, ver, key_data, 184643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt key_data_len); 18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1/4 4-Way Handshake */ 18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_process_1_of_4(sm, src_addr, key, 185043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt ver, key_data, 185143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt key_data_len); 18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) { 18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* PeerKey SMK Handshake */ 185543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt peerkey_rx_eapol_smk(sm, src_addr, key, key_data_len, key_info, 18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver); 18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_MIC) { 18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1/2 Group Key Handshake */ 18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_process_1_of_2(sm, src_addr, key, 186143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt key_data, key_data_len, 186243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt ver); 18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 18658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: EAPOL-Key (Group) without Mic bit - " 18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dropped"); 18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 1; 18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtout: 18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(tmp); 18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE 18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u32 wpa_key_mgmt_suite(struct wpa_sm *sm) 18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (sm->key_mgmt) { 18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_IEEE8021X: 1883f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return ((sm->proto == WPA_PROTO_RSN || 1884f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sm->proto == WPA_PROTO_OSEN) ? 18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_AUTH_KEY_MGMT_UNSPEC_802_1X : 18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_AUTH_KEY_MGMT_UNSPEC_802_1X); 18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_PSK: 18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return (sm->proto == WPA_PROTO_RSN ? 18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X : 18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X); 18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_FT_IEEE8021X: 18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return RSN_AUTH_KEY_MGMT_FT_802_1X; 18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_FT_PSK: 18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return RSN_AUTH_KEY_MGMT_FT_PSK; 18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_IEEE8021X_SHA256: 18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return RSN_AUTH_KEY_MGMT_802_1X_SHA256; 19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_PSK_SHA256: 19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return RSN_AUTH_KEY_MGMT_PSK_SHA256; 19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 1903d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt case WPA_KEY_MGMT_CCKM: 1904d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return (sm->proto == WPA_PROTO_RSN ? 1905d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt RSN_AUTH_KEY_MGMT_CCKM: 1906d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt WPA_AUTH_KEY_MGMT_CCKM); 19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_WPA_NONE: 19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_AUTH_KEY_MGMT_NONE; 19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RSN_SUITE "%02x-%02x-%02x-%d" 19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RSN_SUITE_ARG(s) \ 19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff 19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_get_mib - Dump text list of MIB entries 19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Buffer for the list 19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buflen: Length of the buffer 19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Number of bytes written to buffer 19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used fetch dot11 MIB variables. 19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen) 19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char pmkid_txt[PMKID_LEN * 2 + 1]; 19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int rsna, ret; 19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->cur_pmksa) { 19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt), 19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->cur_pmksa->pmkid, PMKID_LEN); 19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmkid_txt[0] = '\0'; 19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((wpa_key_mgmt_wpa_psk(sm->key_mgmt) || 19418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) && 19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->proto == WPA_PROTO_RSN) 19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsna = 1; 19448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 19458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsna = 0; 19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf, buflen, 19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAOptionImplemented=TRUE\n" 19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAPreauthenticationImplemented=TRUE\n" 19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAEnabled=%s\n" 19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAPreauthenticationEnabled=%s\n" 19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigVersion=%d\n" 19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigPairwiseKeysSupported=5\n" 19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigGroupCipherSize=%d\n" 19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigPMKLifetime=%d\n" 19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigPMKReauthThreshold=%d\n" 19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigNumberOfPTKSAReplayCounters=1\n" 19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigSATimeout=%d\n", 19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsna ? "TRUE" : "FALSE", 19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsna ? "TRUE" : "FALSE", 19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_VERSION, 19624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_cipher_key_len(sm->group_cipher) * 8, 19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAConfigPMKLifetime, 19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAConfigPMKReauthThreshold, 19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAConfigSATimeout); 19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || (size_t) ret >= buflen) 19678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = ret; 19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf( 19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf + len, buflen - len, 19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n" 19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n" 19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n" 19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAPMKIDUsed=%s\n" 19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n" 19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n" 19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n" 19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n" 19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNA4WayHandshakeFailures=%u\n", 19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)), 19824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto, 19834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->pairwise_cipher)), 19844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto, 19854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->group_cipher)), 19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmkid_txt, 19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)), 19884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto, 19894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->pairwise_cipher)), 19904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto, 19914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->group_cipher)), 19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNA4WayHandshakeFailures); 19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret >= 0 && (size_t) ret < buflen) 19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return (int) len; 19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE */ 19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_sm_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry, 2002d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt void *ctx, enum pmksa_free_reason reason) 20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm = ctx; 2005d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt int deauth = 0; 2006d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 2007d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA cache entry free_cb: " 2008d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt MACSTR " reason=%d", MAC2STR(entry->aa), reason); 2009d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 2010d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (sm->cur_pmksa == entry) { 2011d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 2012d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt "RSN: %s current PMKSA entry", 2013d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt reason == PMKSA_REPLACE ? "replaced" : "removed"); 2014d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt pmksa_cache_clear_current(sm); 2015d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 2016d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt /* 2017d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * If an entry is simply being replaced, there's no need to 2018d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * deauthenticate because it will be immediately re-added. 2019d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * This happens when EAP authentication is completed again 2020d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * (reauth or failed PMKSA caching attempt). 2021d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt */ 2022d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (reason != PMKSA_REPLACE) 2023d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt deauth = 1; 2024d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2026d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (reason == PMKSA_EXPIRE && 20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (sm->pmk_len == entry->pmk_len && 20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(sm->pmk, entry->pmk, sm->pmk_len) == 0)) { 20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 2030d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt "RSN: deauthenticating due to expired PMK"); 2031d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt pmksa_cache_clear_current(sm); 2032d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt deauth = 1; 2033d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2035d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (deauth) { 20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(sm->pmk, 0, sizeof(sm->pmk)); 20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); 20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_init - Initialize WPA state machine 20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ctx: Context pointer for callbacks; this needs to be an allocated buffer 20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the allocated WPA state machine data 20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to allocate a new WPA state machine and the returned 20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * value is passed to all WPA state machine calls. 20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx) 20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm; 20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm = os_zalloc(sizeof(*sm)); 20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_init(&sm->pmksa_candidates); 20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->renew_snonce = 1; 20598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ctx = ctx; 20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAConfigPMKLifetime = 43200; 20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAConfigPMKReauthThreshold = 70; 20638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAConfigSATimeout = 60; 20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmksa = pmksa_cache_init(wpa_sm_pmksa_free_cb, sm, sm); 20668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pmksa == NULL) { 20678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, 20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: PMKSA cache initialization failed"); 20698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm); 20708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm; 20748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 20788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_deinit - Deinitialize WPA state machine 20798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 20808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 20818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_deinit(struct wpa_sm *sm) 20828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 20848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_cache_deinit(sm->pmksa); 20868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_sm_start_preauth, sm, NULL); 20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL); 20888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->assoc_wpa_ie); 20898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->ap_wpa_ie); 20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->ap_rsn_ie); 20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->ctx); 20928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey_deinit(sm); 20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->assoc_resp_ies); 20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm); 20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_notify_assoc - Notify WPA state machine about association 21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @bssid: The BSSID of the new association 21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called to let WPA state machine know that the connection 21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * was established. 21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid) 21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int clear_ptk = 1; 21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 21138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Association event - clear replay counter"); 21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->bssid, bssid, ETH_ALEN); 21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(sm->rx_replay_counter, 0, WPA_REPLAY_COUNTER_LEN); 21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->rx_replay_counter_set = 0; 21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->renew_snonce = 1; 21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(sm->preauth_bssid, bssid, ETH_ALEN) == 0) 21228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_deinit(sm); 21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_ft_is_completed(sm)) { 21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Clear portValid to kick EAPOL state machine to re-enter 21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AUTHENTICATED state to get the EAPOL port Authorized. 21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 21308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_notify_portValid(sm->eapol, FALSE); 21318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_key_neg_complete(sm, sm->bssid, 1); 21328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Prepare for the next transition */ 21348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ft_prepare_auth_request(sm, NULL); 21358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt clear_ptk = 0; 21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (clear_ptk) { 21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE 802.11, 8.4.10: Delete PTK SA on (re)association if 21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * this is not part of a Fast BSS Transition. 21448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PTK"); 21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ptk_set = 0; 214761593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt os_memset(&sm->ptk, 0, sizeof(sm->ptk)); 21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->tptk_set = 0; 214961593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt os_memset(&sm->tptk, 0, sizeof(sm->tptk)); 21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS 21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_assoc(sm); 21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS */ 2155cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 2156cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_P2P 2157cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt os_memset(sm->p2p_ip_addr, 0, sizeof(sm->p2p_ip_addr)); 2158cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_P2P */ 21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_notify_disassoc - Notify WPA state machine about disassociation 21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called to let WPA state machine know that the connection 21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * was lost. This will abort any existing pre-authentication session. 21688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 21698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_notify_disassoc(struct wpa_sm *sm) 21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2171fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt peerkey_deinit(sm); 21728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_deinit(sm); 2173d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt pmksa_cache_clear_current(sm); 21748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_get_state(sm) == WPA_4WAY_HANDSHAKE) 21758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNA4WayHandshakeFailures++; 21768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS 21778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_disassoc(sm); 21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS */ 21798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 21808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 21838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_pmk - Set PMK 21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmk: The new PMK 21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmk_len: The length of the new PMK in bytes 21878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Configure the PMK for WPA state machine. 21898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 21908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len) 21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmk_len = pmk_len; 21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->pmk, pmk, pmk_len); 21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 21998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Set XXKey to be PSK for FT key derivation */ 22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->xxkey_len = pmk_len; 22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->xxkey, pmk, pmk_len); 22028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 22038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 22048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_pmk_from_pmksa - Set PMK based on the current PMKSA 22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Take the PMK from the current PMKSA into use. If no PMKSA is active, the PMK 22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * will be cleared. 22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm) 22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 22158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 22178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->cur_pmksa) { 22198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmk_len = sm->cur_pmksa->pmk_len; 22208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->pmk, sm->cur_pmksa->pmk, sm->pmk_len); 22218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 22228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmk_len = PMK_LEN; 22238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(sm->pmk, 0, PMK_LEN); 22248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 22268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 22298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_fast_reauth - Set fast reauthentication (EAP) enabled/disabled 22308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 22318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @fast_reauth: Whether fast reauthentication (EAP) is allowed 22328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 22338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth) 22348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 22358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm) 22368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->fast_reauth = fast_reauth; 22378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 22388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 22418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_scard_ctx - Set context pointer for smartcard callbacks 22428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 22438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @scard_ctx: Context pointer for smartcard related callback functions 22448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 22458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx) 22468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 22478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 22488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 22498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->scard_ctx = scard_ctx; 22508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->preauth_eapol) 22518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_register_scard_ctx(sm->preauth_eapol, scard_ctx); 22528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 22568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_config - Notification of current configration change 22578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 22588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config: Pointer to current network configuration 22598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 22608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Notify WPA state machine that configuration has changed. config will be 22618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * stored as a backpointer to network configuration. This can be %NULL to clear 22628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the stored pointed. 22638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 22648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config) 22658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 22668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm) 22678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 22688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (config) { 22708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->network_ctx = config->network_ctx; 22718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->peerkey_enabled = config->peerkey_enabled; 22728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->allowed_pairwise_cipher = config->allowed_pairwise_cipher; 22738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->proactive_key_caching = config->proactive_key_caching; 22748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_workaround = config->eap_workaround; 22758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_conf_ctx = config->eap_conf_ctx; 22768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (config->ssid) { 22778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->ssid, config->ssid, config->ssid_len); 22788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ssid_len = config->ssid_len; 22798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ssid_len = 0; 22818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ptk_rekey = config->wpa_ptk_rekey; 2282cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt sm->p2p = config->p2p; 22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 22848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->network_ctx = NULL; 22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->peerkey_enabled = 0; 22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->allowed_pairwise_cipher = 0; 22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->proactive_key_caching = 0; 22888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_workaround = 0; 22898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_conf_ctx = NULL; 22908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ssid_len = 0; 22918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ptk_rekey = 0; 2292cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt sm->p2p = 0; 22938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_own_addr - Set own MAC address 22998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 23008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: Own MAC address 23018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 23028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_own_addr(struct wpa_sm *sm, const u8 *addr) 23038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm) 23058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->own_addr, addr, ETH_ALEN); 23068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_ifname - Set network interface name 23118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 23128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ifname: Interface name 23138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @bridge_ifname: Optional bridge interface name (for pre-auth) 23148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 23158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_ifname(struct wpa_sm *sm, const char *ifname, 23168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *bridge_ifname) 23178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm) { 23198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ifname = ifname; 23208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->bridge_ifname = bridge_ifname; 23218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 23268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_eapol - Set EAPOL state machine pointer 23278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 23288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eapol: Pointer to EAPOL state machine allocated with eapol_sm_init() 23298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 23308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_eapol(struct wpa_sm *sm, struct eapol_sm *eapol) 23318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm) 23338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eapol = eapol; 23348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 23388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_param - Set WPA state machine parameters 23398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 23408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @param: Parameter field 23418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @value: Parameter value 23428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 23438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 23448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, 23458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int value) 23468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 23488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 23518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (param) { 23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RSNA_PMK_LIFETIME: 23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (value > 0) 23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAConfigPMKLifetime = value; 23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RSNA_PMK_REAUTH_THRESHOLD: 23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (value > 0 && value <= 100) 23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAConfigPMKReauthThreshold = value; 23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 23648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RSNA_SA_TIMEOUT: 23668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (value > 0) 23678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAConfigSATimeout = value; 23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 23708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PARAM_PROTO: 23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->proto = value; 23738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PARAM_PAIRWISE: 23758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pairwise_cipher = value; 23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PARAM_GROUP: 23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group_cipher = value; 23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PARAM_KEY_MGMT: 23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->key_mgmt = value; 23828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PARAM_MGMT_GROUP: 23858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->mgmt_group_cipher = value; 23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 23888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PARAM_RSN_ENABLED: 23898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->rsn_enabled = value; 23908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PARAM_MFP: 23928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->mfp = value; 23938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 23958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 23998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 24008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 24038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_get_status - Get WPA state machine 24048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 24058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Buffer for status information 24068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buflen: Maximum buffer length 24078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @verbose: Whether to include verbose status information 24088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Number of bytes written to buf. 24098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 24108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Query WPA state machine for status information. This function fills in 24118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * a text area with current status information. If the buffer (buf) is not 24128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * large enough, status information will be truncated to fit the buffer. 24138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 24148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen, 24158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int verbose) 24168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 24178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *pos = buf, *end = buf + buflen; 24188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 24198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(pos, end - pos, 24218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pairwise_cipher=%s\n" 24228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "group_cipher=%s\n" 24238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "key_mgmt=%s\n", 24248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_cipher_txt(sm->pairwise_cipher), 24258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_cipher_txt(sm->group_cipher), 24268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_key_mgmt_txt(sm->key_mgmt, sm->proto)); 24278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || ret >= end - pos) 24288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos - buf; 24298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ret; 2430d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 2431d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (sm->mfp != NO_MGMT_FRAME_PROTECTION && sm->ap_rsn_ie) { 2432d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt struct wpa_ie_data rsn; 2433d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn) 2434d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt >= 0 && 2435d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt rsn.capabilities & (WPA_CAPABILITY_MFPR | 2436d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt WPA_CAPABILITY_MFPC)) { 2437d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt ret = os_snprintf(pos, end - pos, "pmf=%d\n", 2438d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt (rsn.capabilities & 2439d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt WPA_CAPABILITY_MFPR) ? 2 : 1); 2440d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (ret < 0 || ret >= end - pos) 2441d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return pos - buf; 2442d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt pos += ret; 2443d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 2444d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 2445d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 24468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos - buf; 24478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 24488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2450f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidtint wpa_sm_pmf_enabled(struct wpa_sm *sm) 2451f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt{ 2452f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt struct wpa_ie_data rsn; 2453f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt 2454f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt if (sm->mfp == NO_MGMT_FRAME_PROTECTION || !sm->ap_rsn_ie) 2455f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt return 0; 2456f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt 2457f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn) >= 0 && 2458f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt rsn.capabilities & (WPA_CAPABILITY_MFPR | WPA_CAPABILITY_MFPC)) 2459f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt return 1; 2460f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt 2461f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt return 0; 2462f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt} 2463f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt 2464f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt 24658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 24668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_assoc_wpa_ie_default - Generate own WPA/RSN IE from configuration 24678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 24688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_ie: Pointer to buffer for WPA/RSN IE 24698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_ie_len: Pointer to the length of the wpa_ie buffer 24708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 24718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 24728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie, 24738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t *wpa_ie_len) 24748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 24758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 24768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 24788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 24798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wpa_gen_wpa_ie(sm, wpa_ie, *wpa_ie_len); 24818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) 24828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 24838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *wpa_ie_len = res; 24848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Set own WPA IE default", 24868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ie, *wpa_ie_len); 24878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->assoc_wpa_ie == NULL) { 24898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 24908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Make a copy of the WPA/RSN IE so that 4-Way Handshake gets 24918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the correct version of the IE even if PMKSA caching is 24928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * aborted (which would remove PMKID from IE generation). 24938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 24948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->assoc_wpa_ie = os_malloc(*wpa_ie_len); 24958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->assoc_wpa_ie == NULL) 24968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 24978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->assoc_wpa_ie, wpa_ie, *wpa_ie_len); 24998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->assoc_wpa_ie_len = *wpa_ie_len; 25008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 25038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 25048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 25078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_assoc_wpa_ie - Set own WPA/RSN IE from (Re)AssocReq 25088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 25098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ie: Pointer to IE data (starting from id) 25108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: IE length 25118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 25128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 25138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Inform WPA state machine about the WPA/RSN IE used in (Re)Association 25148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Request frame. The IE will be used to override the default value generated 25158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * with wpa_sm_set_assoc_wpa_ie_default(). 25168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 25178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_set_assoc_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len) 25188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 25198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 25208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 25218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->assoc_wpa_ie); 25238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie == NULL || len == 0) { 25248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 25258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: clearing own WPA/RSN IE"); 25268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->assoc_wpa_ie = NULL; 25278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->assoc_wpa_ie_len = 0; 25288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 25298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: set own WPA/RSN IE", ie, len); 25308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->assoc_wpa_ie = os_malloc(len); 25318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->assoc_wpa_ie == NULL) 25328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 25338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->assoc_wpa_ie, ie, len); 25358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->assoc_wpa_ie_len = len; 25368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 25398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 25408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 25438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_ap_wpa_ie - Set AP WPA IE from Beacon/ProbeResp 25448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 25458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ie: Pointer to IE data (starting from id) 25468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: IE length 25478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 25488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 25498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Inform WPA state machine about the WPA IE used in Beacon / Probe Response 25508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * frame. 25518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 25528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len) 25538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 25548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 25558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 25568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->ap_wpa_ie); 25588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie == NULL || len == 0) { 25598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 25608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: clearing AP WPA IE"); 25618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ap_wpa_ie = NULL; 25628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ap_wpa_ie_len = 0; 25638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 25648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: set AP WPA IE", ie, len); 25658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ap_wpa_ie = os_malloc(len); 25668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->ap_wpa_ie == NULL) 25678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 25688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->ap_wpa_ie, ie, len); 25708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ap_wpa_ie_len = len; 25718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 25748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 25758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 25788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_ap_rsn_ie - Set AP RSN IE from Beacon/ProbeResp 25798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 25808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ie: Pointer to IE data (starting from id) 25818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: IE length 25828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 25838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 25848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Inform WPA state machine about the RSN IE used in Beacon / Probe Response 25858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * frame. 25868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 25878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len) 25888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 25898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 25908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 25918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->ap_rsn_ie); 25938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie == NULL || len == 0) { 25948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 25958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: clearing AP RSN IE"); 25968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ap_rsn_ie = NULL; 25978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ap_rsn_ie_len = 0; 25988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 25998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: set AP RSN IE", ie, len); 26008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ap_rsn_ie = os_malloc(len); 26018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->ap_rsn_ie == NULL) 26028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 26038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->ap_rsn_ie, ie, len); 26058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ap_rsn_ie_len = len; 26068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 26078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 26098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 26138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_parse_own_wpa_ie - Parse own WPA/RSN IE 26148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 26158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Pointer to data area for parsing results 26168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 if IE is not known, or -2 on parsing failure 26178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 26188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Parse the contents of the own WPA or RSN IE from (Re)AssocReq and write the 26198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * parsed data into data. 26208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 26218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, struct wpa_ie_data *data) 26228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 26248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 26258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->assoc_wpa_ie == NULL) { 26278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 26288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: No WPA/RSN IE available from association info"); 26298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 26308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 26318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_parse_wpa_ie(sm->assoc_wpa_ie, sm->assoc_wpa_ie_len, data)) 26328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -2; 26338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 26348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len) 26388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pmksa_cache_list(sm->pmksa, buf, len); 26408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 264321de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt#ifdef CONFIG_TESTING_OPTIONS 26448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_drop_sa(struct wpa_sm *sm) 26458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PMK and PTK"); 26478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ptk_set = 0; 26488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->tptk_set = 0; 26498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(sm->pmk, 0, sizeof(sm->pmk)); 26508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&sm->ptk, 0, sizeof(sm->ptk)); 26518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&sm->tptk, 0, sizeof(sm->tptk)); 26528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 265321de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt#endif /* CONFIG_TESTING_OPTIONS */ 26548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_has_ptk(struct wpa_sm *sm) 26578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 26598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 26608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->ptk_set; 26618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid wpa_sm_update_replay_ctr(struct wpa_sm *sm, const u8 *replay_ctr) 26651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 26661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(sm->rx_replay_counter, replay_ctr, WPA_REPLAY_COUNTER_LEN); 26671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 26681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid wpa_sm_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx) 26711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 2672f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt pmksa_cache_flush(sm->pmksa, network_ctx, NULL, 0); 26731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 267461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 267561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2676a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#ifdef CONFIG_WNM 267761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf) 267861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 267961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u16 keyinfo; 268061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 keylen; /* plaintext key len */ 268161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 *key_rsc; 268261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 268361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (subelem_id == WNM_SLEEP_SUBELEM_GTK) { 268461593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt struct wpa_gtk_data gd; 268561593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt 268661593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt os_memset(&gd, 0, sizeof(gd)); 268761593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt keylen = wpa_cipher_key_len(sm->group_cipher); 268861593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt gd.key_rsc_len = wpa_cipher_rsc_len(sm->group_cipher); 268961593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt gd.alg = wpa_cipher_to_alg(sm->group_cipher); 269061593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt if (gd.alg == WPA_ALG_NONE) { 269161593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt wpa_printf(MSG_DEBUG, "Unsupported group cipher suite"); 269261593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt return -1; 269361593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt } 269461593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt 269561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt key_rsc = buf + 5; 2696a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt keyinfo = WPA_GET_LE16(buf + 2); 269761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gd.gtk_len = keylen; 269861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (gd.gtk_len != buf[4]) { 269961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "GTK len mismatch len %d vs %d", 270061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gd.gtk_len, buf[4]); 270161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 270261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 270361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gd.keyidx = keyinfo & 0x03; /* B0 - B1 */ 270461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gd.tx = wpa_supplicant_gtk_tx_bit_workaround( 270561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sm, !!(keyinfo & WPA_KEY_INFO_TXRX)); 270661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2707a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt os_memcpy(gd.gtk, buf + 13, gd.gtk_len); 270861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 270961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "Install GTK (WNM SLEEP)", 271061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gd.gtk, gd.gtk_len); 271161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_supplicant_install_gtk(sm, &gd, key_rsc)) { 271261593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt os_memset(&gd, 0, sizeof(gd)); 271361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to install the GTK in " 271461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "WNM mode"); 271561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 271661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 271761593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt os_memset(&gd, 0, sizeof(gd)); 271861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_IEEE80211W 271961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else if (subelem_id == WNM_SLEEP_SUBELEM_IGTK) { 272061593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt struct wpa_igtk_kde igd; 272161593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt u16 keyidx; 272261593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt 272361593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt os_memset(&igd, 0, sizeof(igd)); 2724b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt keylen = wpa_cipher_key_len(sm->mgmt_group_cipher); 272561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_memcpy(igd.keyid, buf + 2, 2); 272661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_memcpy(igd.pn, buf + 4, 6); 272761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 272861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt keyidx = WPA_GET_LE16(igd.keyid); 2729b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt os_memcpy(igd.igtk, buf + 10, keylen); 273061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 273161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "Install IGTK (WNM SLEEP)", 2732b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt igd.igtk, keylen); 2733b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher), 2734b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt broadcast_ether_addr, 273561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt keyidx, 0, igd.pn, sizeof(igd.pn), 2736b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt igd.igtk, keylen) < 0) { 273761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to install the IGTK in " 273861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "WNM mode"); 273961593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt os_memset(&igd, 0, sizeof(igd)); 274061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 274161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 274261593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt os_memset(&igd, 0, sizeof(igd)); 274361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 274461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else { 274561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "Unknown element id"); 274661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 274761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 274861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 274961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 275061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 2751a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#endif /* CONFIG_WNM */ 2752fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 2753fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 2754fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt#ifdef CONFIG_PEERKEY 2755fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidtint wpa_sm_rx_eapol_peerkey(struct wpa_sm *sm, const u8 *src_addr, 2756fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt const u8 *buf, size_t len) 2757fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt{ 2758fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct wpa_peerkey *peerkey; 2759fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 2760fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { 2761fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (os_memcmp(peerkey->addr, src_addr, ETH_ALEN) == 0) 2762fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt break; 2763fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 2764fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 2765fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (!peerkey) 2766fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return 0; 2767fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 2768fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_sm_rx_eapol(sm, src_addr, buf, len); 2769fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 2770fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return 1; 2771fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt} 2772fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 2773cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 2774cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 2775cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_P2P 2776cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 2777cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtint wpa_sm_get_p2p_ip_addr(struct wpa_sm *sm, u8 *buf) 2778cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{ 2779cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (sm == NULL || WPA_GET_BE32(sm->p2p_ip_addr) == 0) 2780cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return -1; 2781cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt os_memcpy(buf, sm->p2p_ip_addr, 3 * 4); 2782cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return 0; 2783cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt} 2784cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 2785cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_P2P */ 2786