wpa.c revision cce06667447b5aec83452adb0c15100ada531095
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 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->key_mgmt) || wpa_key_mgmt_sha256(sm->key_mgmt)) 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = WPA_KEY_INFO_TYPE_AES_128_CMAC; 9461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt else if (sm->pairwise_cipher != WPA_CIPHER_TKIP) 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_get_bssid(sm, bssid) < 0) { 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Failed to read BSSID for EAPOL-Key request"); 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(*reply), &rlen, (void *) &reply); 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply->type = sm->proto == WPA_PROTO_RSN ? 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = WPA_KEY_INFO_REQUEST | ver; 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->ptk_set) 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info |= WPA_KEY_INFO_MIC; 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (error) 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info |= WPA_KEY_INFO_ERROR; 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pairwise) 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info |= WPA_KEY_INFO_KEY_TYPE; 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_info, key_info); 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_length, 0); 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply->replay_counter, sm->request_counter, 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_data_length, 0); 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Sending EAPOL-Key Request (error=%d " 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pairwise=%d ptk_set=%d len=%lu)", 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt error, pairwise, sm->ptk_set, (unsigned long) rlen); 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL, 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf, rlen, key_info & WPA_KEY_INFO_MIC ? 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply->key_mic : NULL); 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_get_pmk(struct wpa_sm *sm, 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pmkid) 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int abort_cached = 0; 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmkid && !sm->cur_pmksa) { 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* When using drivers that generate RSN IE, wpa_supplicant may 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * not have enough time to get the association information 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * event before receiving this 1/4 message, so try to find a 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * matching PMKSA cache entry here. */ 148c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sm->cur_pmksa = pmksa_cache_get(sm->pmksa, src_addr, pmkid, 149c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt NULL); 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->cur_pmksa) { 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: found matching PMKID from PMKSA cache"); 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: no matching PMKID found"); 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt abort_cached = 1; 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmkid && sm->cur_pmksa && 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(pmkid, sm->cur_pmksa->pmkid, PMKID_LEN) == 0) { 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: matched PMKID", pmkid, PMKID_LEN); 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_set_pmk_from_pmksa(sm); 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from PMKSA cache", 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmk, sm->pmk_len); 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_notify_cached(sm->eapol); 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->xxkey_len = 0; 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) && sm->eapol) { 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res, pmk_len; 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmk_len = PMK_LEN; 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eapol_sm_get_key(sm->eapol, sm->pmk, PMK_LEN); 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res) { 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-LEAP is an exception from other EAP methods: it 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * uses only 16-byte PMK. 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eapol_sm_get_key(sm->eapol, sm->pmk, 16); 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmk_len = 16; 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 buf[2 * PMK_LEN]; 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eapol_sm_get_key(sm->eapol, buf, 2 * PMK_LEN) == 0) 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->xxkey, buf + PMK_LEN, PMK_LEN); 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->xxkey_len = PMK_LEN; 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(buf, 0, sizeof(buf)); 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == 0) { 19361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct rsn_pmksa_cache_entry *sa = NULL; 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPA: PMK from EAPOL state " 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "machines", sm->pmk, pmk_len); 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmk_len = pmk_len; 197c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt if (sm->proto == WPA_PROTO_RSN && 198c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt !wpa_key_mgmt_ft(sm->key_mgmt)) { 19961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sa = pmksa_cache_add(sm->pmksa, 20061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sm->pmk, pmk_len, 20161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt src_addr, sm->own_addr, 20261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sm->network_ctx, 20361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sm->key_mgmt); 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->cur_pmksa && pmkid && 206c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pmksa_cache_get(sm->pmksa, src_addr, pmkid, NULL)) 207c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt { 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: the new PMK matches with the " 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PMKID"); 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt abort_cached = 0; 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 21461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!sm->cur_pmksa) 21561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sm->cur_pmksa = sa; 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Failed to get master session key from " 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAPOL state machines - key handshake " 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "aborted"); 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->cur_pmksa) { 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: Cancelled PMKSA caching " 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "attempt"); 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->cur_pmksa = NULL; 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt abort_cached = 1; 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (!abort_cached) { 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 233c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt if (abort_cached && wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) && 234c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt !wpa_key_mgmt_ft(sm->key_mgmt)) { 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Send EAPOL-Start to trigger full EAP authentication. */ 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf; 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buflen; 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: no PMKSA entry found - trigger " 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "full EAP authentication"); 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START, 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0, &buflen, NULL); 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf) { 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_ether_send(sm, sm->bssid, ETH_P_EAPOL, 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf, buflen); 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -2; 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_send_2_of_4 - Send message 2 of WPA/RSN 4-Way Handshake 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dst: Destination address for the frame 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key: Pointer to the EAPOL-Key frame header 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ver: Version bits from EAPOL-Key Key Info 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @nonce: Nonce value for the EAPOL-Key frame 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_ie: WPA/RSN IE 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_ie_len: Length of the WPA/RSN IE 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ptk: PTK to use for keyed hash and encryption 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ver, const u8 *nonce, 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *wpa_ie, size_t wpa_ie_len, 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ptk *ptk) 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rlen; 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *reply; 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rbuf; 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rsn_ie_buf = NULL; 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_ie == NULL) { 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No wpa_ie set - " 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "cannot generate msg 2/4"); 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->key_mgmt)) { 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Add PMKR1Name into RSN IE (PMKID-List) and add MDIE and 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * FTIE from (Re)Association Response. 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_ie_buf = os_malloc(wpa_ie_len + 2 + 2 + PMKID_LEN + 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->assoc_resp_ies_len); 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rsn_ie_buf == NULL) 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(rsn_ie_buf, wpa_ie, wpa_ie_len); 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wpa_insert_pmkid(rsn_ie_buf, wpa_ie_len, 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmk_r1_name); 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rsn_ie_buf); 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ie_len += res; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->assoc_resp_ies) { 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(rsn_ie_buf + wpa_ie_len, sm->assoc_resp_ies, 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->assoc_resp_ies_len); 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ie_len += sm->assoc_resp_ies_len; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ie = rsn_ie_buf; 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len); 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, sizeof(*reply) + wpa_ie_len, 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &rlen, (void *) &reply); 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) { 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rsn_ie_buf); 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply->type = sm->proto == WPA_PROTO_RSN ? 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_info, 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC); 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->proto == WPA_PROTO_RSN) 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_length, 0); 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply->key_length, key->key_length, 2); 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply->replay_counter, key->replay_counter, 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter", reply->replay_counter, 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_data_length, wpa_ie_len); 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply + 1, wpa_ie, wpa_ie_len); 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rsn_ie_buf); 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN); 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/4"); 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL, 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf, rlen, reply->key_mic); 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr, 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ptk *ptk) 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 35961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t ptk_len = sm->pairwise_cipher != WPA_CIPHER_TKIP ? 48 : 64; 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->key_mgmt)) 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_derive_ptk_ft(sm, src_addr, key, ptk, ptk_len); 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion", 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->own_addr, sm->bssid, sm->snonce, key->key_nonce, 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) ptk, ptk_len, 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_key_mgmt_sha256(sm->key_mgmt)); 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 ver) 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse ie; 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ptk *ptk; 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 buf[8]; 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_get_network_ctx(sm) == NULL) { 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No SSID info " 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "found (msg 1 of 4)"); 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE); 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of 4-Way " 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver); 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&ie, 0, sizeof(ie)); 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->proto == WPA_PROTO_RSN) { 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RSN: msg 1/4 should contain PMKID for the selected PMK */ 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *_buf = (const u8 *) (key + 1); 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len = WPA_GET_BE16(key->key_data_length); 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", _buf, len); 4001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_supplicant_parse_ies(_buf, len, &ie) < 0) 4011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto failed; 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie.pmkid) { 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: PMKID from " 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Authenticator", ie.pmkid, PMKID_LEN); 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid); 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == -2) { 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: Do not reply to " 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "msg 1/4 - requesting full EAP authentication"); 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res) 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->renew_snonce) { 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) { 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Failed to get random data for SNonce"); 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->renew_snonce = 0; 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce", 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->snonce, WPA_NONCE_LEN); 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Calculate PTK which will be stored as a temporary PTK until it has 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * been verified when processing message 3/4. */ 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ptk = &sm->tptk; 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_derive_ptk(sm, src_addr, key, ptk); 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Supplicant: swap tx/rx Mic keys */ 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf, ptk->u.auth.tx_mic_key, 8); 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ptk->u.auth.tx_mic_key, ptk->u.auth.rx_mic_key, 8); 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ptk->u.auth.rx_mic_key, buf, 8); 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->tptk_set = 1; 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, sm->snonce, 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->assoc_wpa_ie, sm->assoc_wpa_ie_len, 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ptk)) 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->anonce, key->key_nonce, WPA_NONCE_LEN); 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfailed: 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_sm_start_preauth(void *eloop_ctx, void *timeout_ctx) 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm = eloop_ctx; 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_candidate_process(sm); 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_key_neg_complete(struct wpa_sm *sm, 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, int secure) 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Key negotiation completed with " 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " [PTK=%s GTK=%s]", MAC2STR(addr), 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_cipher_txt(sm->pairwise_cipher), 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_cipher_txt(sm->group_cipher)); 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_cancel_auth_timeout(sm); 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_set_state(sm, WPA_COMPLETED); 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (secure) { 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_mlme_setprotection( 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, addr, MLME_SETPROTECTION_PROTECT_TYPE_RX_TX, 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_notify_portValid(sm->eapol, TRUE); 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_wpa_psk(sm->key_mgmt)) 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_notify_eap_success(sm->eapol, TRUE); 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Start preauthentication after a short wait to avoid a 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * possible race condition between the data receive and key 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * configuration after the 4-Way Handshake. This increases the 4801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * likelihood of the first preauth EAPOL-Start frame getting to 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the target AP. 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(1, 0, wpa_sm_start_preauth, sm, NULL); 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->cur_pmksa && sm->cur_pmksa->opportunistic) { 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: Authenticator accepted " 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "opportunistic PMKSA entry - marking it valid"); 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->cur_pmksa->opportunistic = 0; 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->key_mgmt)) { 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Prepare for the next transition */ 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ft_prepare_auth_request(sm, NULL); 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_sm_rekey_ptk(void *eloop_ctx, void *timeout_ctx) 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm = eloop_ctx; 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Request PTK rekeying"); 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_key_request(sm, 0, 1); 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_install_ptk(struct wpa_sm *sm, 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key) 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int keylen, rsclen; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wpa_alg alg; 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *key_rsc; 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Installing PTK to the driver"); 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (sm->pairwise_cipher == WPA_CIPHER_NONE) { 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Pairwise Cipher " 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Suite: NONE - do not use pairwise keys"); 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 5264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 5274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) { 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Unsupported pairwise cipher %d", 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pairwise_cipher); 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt alg = wpa_cipher_to_alg(sm->pairwise_cipher); 5354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt keylen = wpa_cipher_key_len(sm->pairwise_cipher); 5364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt rsclen = wpa_cipher_rsc_len(sm->pairwise_cipher); 5374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->proto == WPA_PROTO_RSN) { 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_rsc = null_rsc; 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_rsc = key->key_rsc; 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, rsclen); 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_set_key(sm, alg, sm->bssid, 0, 1, key_rsc, rsclen, 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) sm->ptk.tk1, keylen) < 0) { 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Failed to set PTK to the " 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "driver (alg=%d keylen=%d bssid=" MACSTR ")", 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt alg, keylen, MAC2STR(sm->bssid)); 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_ptk_rekey) { 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL); 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(sm->wpa_ptk_rekey, 0, wpa_sm_rekey_ptk, 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, NULL); 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_check_group_cipher(struct wpa_sm *sm, 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int group_cipher, 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int keylen, int maxkeylen, 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int *key_rsc_len, 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wpa_alg *alg) 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt int klen; 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt *alg = wpa_cipher_to_alg(group_cipher); 5734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (*alg == WPA_ALG_NONE) { 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Unsupported Group Cipher %d", 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group_cipher); 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt *key_rsc_len = wpa_cipher_rsc_len(group_cipher); 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt klen = wpa_cipher_key_len(group_cipher); 5824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (keylen != klen || maxkeylen < klen) { 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Unsupported %s Group Cipher key length %d (%d)", 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_cipher_txt(group_cipher), keylen, maxkeylen); 5864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return -1; 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_gtk_data { 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wpa_alg alg; 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tx, key_rsc_len, keyidx; 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 gtk[32]; 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int gtk_len; 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_install_gtk(struct wpa_sm *sm, 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_gtk_data *gd, 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *key_rsc) 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *_gtk = gd->gtk; 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 gtk_buf[32]; 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPA: Group Key", gd->gtk, gd->gtk_len); 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Installing GTK to the driver (keyidx=%d tx=%d len=%d)", 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd->keyidx, gd->tx, gd->gtk_len); 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, gd->key_rsc_len); 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->group_cipher == WPA_CIPHER_TKIP) { 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Swap Tx/Rx keys for Michael MIC */ 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(gtk_buf, gd->gtk, 16); 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(gtk_buf + 16, gd->gtk + 24, 8); 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(gtk_buf + 24, gd->gtk + 16, 8); 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _gtk = gtk_buf; 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pairwise_cipher == WPA_CIPHER_NONE) { 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_set_key(sm, gd->alg, NULL, 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd->keyidx, 1, key_rsc, gd->key_rsc_len, 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _gtk, gd->gtk_len) < 0) { 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Failed to set GTK to the driver " 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(Group only)"); 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (wpa_sm_set_key(sm, gd->alg, broadcast_ether_addr, 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd->keyidx, gd->tx, key_rsc, gd->key_rsc_len, 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _gtk, gd->gtk_len) < 0) { 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Failed to set GTK to " 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the driver (alg=%d keylen=%d keyidx=%d)", 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd->alg, gd->gtk_len, gd->keyidx); 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_gtk_tx_bit_workaround(const struct wpa_sm *sm, 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tx) 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tx && sm->pairwise_cipher != WPA_CIPHER_NONE) { 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Ignore Tx bit for GTK if a pairwise key is used. One AP 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * seemed to set this bit (incorrectly, since Tx is only when 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * doing Group Key only APs) and without this workaround, the 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * data connection does not work because wpa_supplicant 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * configured non-zero keyidx to be used for unicast. */ 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Tx bit set for GTK, but pairwise " 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "keys are used - ignore Tx bit"); 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return tx; 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm, 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *gtk, size_t gtk_len, 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int key_info) 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_gtk_data gd; 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames - Figure 43x 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * GTK KDE format: 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * KeyID[bits 0-1], Tx [bit 2], Reserved [bits 3-7] 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Reserved [bits 0-7] 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * GTK 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&gd, 0, sizeof(gd)); 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "RSN: received GTK in pairwise handshake", 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gtk, gtk_len); 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gtk_len < 2 || gtk_len - 2 > sizeof(gd.gtk)) 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd.keyidx = gtk[0] & 0x3; 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd.tx = wpa_supplicant_gtk_tx_bit_workaround(sm, 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !!(gtk[0] & BIT(2))); 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gtk += 2; 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gtk_len -= 2; 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(gd.gtk, gtk, gtk_len); 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd.gtk_len = gtk_len; 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher, 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gtk_len, gtk_len, 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &gd.key_rsc_len, &gd.alg) || 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_install_gtk(sm, &gd, key->key_rsc)) { 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: Failed to install GTK"); 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_key_neg_complete(sm, sm->bssid, 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info & WPA_KEY_INFO_SECURE); 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee80211w_set_keys(struct wpa_sm *sm, 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *ie) 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie->igtk) { 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_igtk_kde *igtk; 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 keyidx; 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie->igtk_len != sizeof(*igtk)) 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt igtk = (const struct wpa_igtk_kde *) ie->igtk; 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keyidx = WPA_GET_LE16(igtk->keyid); 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: IGTK keyid %d " 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pn %02x%02x%02x%02x%02x%02x", 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keyidx, MAC2STR(igtk->pn)); 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK", 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt igtk->igtk, WPA_IGTK_LEN); 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keyidx > 4095) { 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Invalid IGTK KeyID %d", keyidx); 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_set_key(sm, WPA_ALG_IGTK, broadcast_ether_addr, 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keyidx, 0, igtk->pn, sizeof(igtk->pn), 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt igtk->igtk, WPA_IGTK_LEN) < 0) { 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Failed to configure IGTK to the driver"); 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_IEEE80211W */ 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_report_ie_mismatch(struct wpa_sm *sm, 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *reason, const u8 *src_addr, 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *wpa_ie, size_t wpa_ie_len, 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *rsn_ie, size_t rsn_ie_len) 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: %s (src=" MACSTR ")", 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reason, MAC2STR(src_addr)); 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->ap_wpa_ie) { 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_INFO, "WPA: WPA IE in Beacon/ProbeResp", 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ap_wpa_ie, sm->ap_wpa_ie_len); 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_ie) { 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->ap_wpa_ie) { 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: No WPA IE in Beacon/ProbeResp"); 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_INFO, "WPA: WPA IE in 3/4 msg", 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ie, wpa_ie_len); 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->ap_rsn_ie) { 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_INFO, "WPA: RSN IE in Beacon/ProbeResp", 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ap_rsn_ie, sm->ap_rsn_ie_len); 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rsn_ie) { 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->ap_rsn_ie) { 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: No RSN IE in Beacon/ProbeResp"); 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_INFO, "WPA: RSN IE in 3/4 msg", 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_ie, rsn_ie_len); 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 780d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_sm_deauthenticate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS); 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ft_validate_mdie(struct wpa_sm *sm, 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *ie, 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *assoc_resp_mdie) 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_mdie *mdie; 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mdie = (struct rsn_mdie *) (ie->mdie + 2); 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie->mdie == NULL || ie->mdie_len < 2 + sizeof(*mdie) || 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(mdie->mobility_domain, sm->mobility_domain, 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MOBILITY_DOMAIN_ID_LEN) != 0) { 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: MDIE in msg 3/4 did " 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not match with the current mobility domain"); 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (assoc_resp_mdie && 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (assoc_resp_mdie[1] != ie->mdie[1] || 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(assoc_resp_mdie, ie->mdie, 2 + ie->mdie[1]) != 0)) { 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: MDIE mismatch"); 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: MDIE in EAPOL-Key msg 3/4", 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->mdie, 2 + ie->mdie[1]); 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: MDIE in (Re)Association Response", 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt assoc_resp_mdie, 2 + assoc_resp_mdie[1]); 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ft_validate_ftie(struct wpa_sm *sm, 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *ie, 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *assoc_resp_ftie) 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie->ftie == NULL) { 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FT: No FTIE in EAPOL-Key msg 3/4"); 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (assoc_resp_ftie == NULL) 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (assoc_resp_ftie[1] != ie->ftie[1] || 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(assoc_resp_ftie, ie->ftie, 2 + ie->ftie[1]) != 0) { 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: FTIE mismatch"); 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 3/4", 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->ftie, 2 + ie->ftie[1]); 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)Association Response", 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt assoc_resp_ftie, 2 + assoc_resp_ftie[1]); 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ft_validate_rsnie(struct wpa_sm *sm, 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *ie) 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data rsn; 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ie->rsn_ie) 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Verify that PMKR1Name from EAPOL-Key message 3/4 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * matches with the value we derived. 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_parse_wpa_ie_rsn(ie->rsn_ie, ie->rsn_ie_len, &rsn) < 0 || 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn.num_pmkid != 1 || rsn.pmkid == NULL) { 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: No PMKR1Name in " 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FT 4-way handshake message 3/4"); 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(rsn.pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0) { 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FT: PMKR1Name mismatch in " 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FT 4-way handshake message 3/4"); 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Authenticator", 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn.pmkid, WPA_PMK_NAME_LEN); 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name", 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmk_r1_name, WPA_PMK_NAME_LEN); 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_validate_ie_ft(struct wpa_sm *sm, 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *ie) 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end, *mdie = NULL, *ftie = NULL; 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->assoc_resp_ies) { 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = sm->assoc_resp_ies; 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + sm->assoc_resp_ies_len; 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos + 2 < end) { 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + 2 + pos[1] > end) 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (*pos) { 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WLAN_EID_MOBILITY_DOMAIN: 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mdie = pos; 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WLAN_EID_FAST_BSS_TRANSITION: 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = pos; 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + pos[1]; 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ft_validate_mdie(sm, src_addr, ie, mdie) < 0 || 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ft_validate_ftie(sm, src_addr, ie, ftie) < 0 || 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ft_validate_rsnie(sm, src_addr, ie) < 0) 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_validate_ie(struct wpa_sm *sm, 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *ie) 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->ap_wpa_ie == NULL && sm->ap_rsn_ie == NULL) { 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: No WPA/RSN IE for this AP known. " 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Trying to get from scan results"); 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_get_beacon_ie(sm) < 0) { 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Could not find AP from " 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the scan results"); 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Found the current AP from " 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "updated scan results"); 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie->wpa_ie == NULL && ie->rsn_ie == NULL && 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (sm->ap_wpa_ie || sm->ap_rsn_ie)) { 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match " 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "with IE in Beacon/ProbeResp (no IE?)", 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt src_addr, ie->wpa_ie, ie->wpa_ie_len, 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->rsn_ie, ie->rsn_ie_len); 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((ie->wpa_ie && sm->ap_wpa_ie && 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (ie->wpa_ie_len != sm->ap_wpa_ie_len || 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(ie->wpa_ie, sm->ap_wpa_ie, ie->wpa_ie_len) != 0)) || 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (ie->rsn_ie && sm->ap_rsn_ie && 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_compare_rsn_ie(wpa_key_mgmt_ft(sm->key_mgmt), 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ap_rsn_ie, sm->ap_rsn_ie_len, 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->rsn_ie, ie->rsn_ie_len))) { 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match " 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "with IE in Beacon/ProbeResp", 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt src_addr, ie->wpa_ie, ie->wpa_ie_len, 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->rsn_ie, ie->rsn_ie_len); 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->proto == WPA_PROTO_WPA && 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->rsn_ie && sm->ap_rsn_ie == NULL && sm->rsn_enabled) { 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_report_ie_mismatch(sm, "Possible downgrade attack " 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "detected - RSN was enabled and RSN IE " 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "was in msg 3/4, but not in " 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Beacon/ProbeResp", 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt src_addr, ie->wpa_ie, ie->wpa_ie_len, 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->rsn_ie, ie->rsn_ie_len); 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->key_mgmt) && 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_validate_ie_ft(sm, src_addr, ie) < 0) 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_send_4_of_4 - Send message 4 of WPA/RSN 4-Way Handshake 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dst: Destination address for the frame 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key: Pointer to the EAPOL-Key frame header 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ver: Version bits from EAPOL-Key Key Info 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key_info: Key Info 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @kde: KDEs to include the EAPOL-Key frame 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @kde_len: Length of KDEs 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ptk: PTK to use for keyed hash and encryption 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst, 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 ver, u16 key_info, 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *kde, size_t kde_len, 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ptk *ptk) 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rlen; 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *reply; 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rbuf; 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde) 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: KDE for msg 4/4", kde, kde_len); 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(*reply) + kde_len, 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &rlen, (void *) &reply); 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply->type = sm->proto == WPA_PROTO_RSN ? 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info &= WPA_KEY_INFO_SECURE; 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info |= ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC; 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_info, key_info); 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->proto == WPA_PROTO_RSN) 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_length, 0); 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply->key_length, key->key_length, 2); 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply->replay_counter, key->replay_counter, 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_data_length, kde_len); 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde) 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply + 1, kde, kde_len); 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 4/4"); 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL, 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf, rlen, reply->key_mic); 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 ver) 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info, keylen, len; 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse ie; 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE); 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 3 of 4-Way " 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Handshake from " MACSTR " (ver=%d)", MAC2STR(sm->bssid), ver); 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = WPA_GET_BE16(key->key_info); 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (const u8 *) (key + 1); 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = WPA_GET_BE16(key->key_data_length); 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", pos, len); 10501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_supplicant_parse_ies(pos, len, &ie) < 0) 10511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto failed; 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: GTK IE in unencrypted key data"); 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie.igtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: IGTK KDE in unencrypted key data"); 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie.igtk && ie.igtk_len != sizeof(struct wpa_igtk_kde)) { 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Invalid IGTK KDE length %lu", 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) ie.igtk_len); 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0) 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) { 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: ANonce from message 1 of 4-Way Handshake " 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "differs from 3 of 4-Way Handshake - drop packet (src=" 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR ")", MAC2STR(sm->bssid)); 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keylen = WPA_GET_BE16(key->key_length); 10844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (keylen != wpa_cipher_key_len(sm->pairwise_cipher)) { 10854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 10864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt "WPA: Invalid %s key length %d (src=" MACSTR 10874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt ")", wpa_cipher_txt(sm->pairwise_cipher), keylen, 10884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt MAC2STR(sm->bssid)); 10894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt goto failed; 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info, 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0, &sm->ptk)) { 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SNonce was successfully used in msg 3/4, so mark it to be renewed 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * for the next 4-Way Handshake. If msg 3 is received again, the old 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SNonce will still be used to avoid changing PTK. */ 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->renew_snonce = 1; 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_INSTALL) { 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_install_ptk(sm, key)) 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_SECURE) { 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_mlme_setprotection( 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, sm->bssid, MLME_SETPROTECTION_PROTECT_TYPE_RX, 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_notify_portValid(sm->eapol, TRUE); 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE); 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie.gtk && 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_pairwise_gtk(sm, key, 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie.gtk, ie.gtk_len, key_info) < 0) { 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: Failed to configure GTK"); 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ieee80211w_set_keys(sm, &ie) < 0) { 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: Failed to configure IGTK"); 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1129cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (ie.gtk) 1130cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_sm_set_rekey_offload(sm); 11311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfailed: 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm, 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *keydata, 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t keydatalen, 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info, 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_gtk_data *gd) 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int maxkeylen; 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse ie; 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: msg 1/2 key data", keydata, keydatalen); 11491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_supplicant_parse_ies(keydata, keydatalen, &ie) < 0) 11501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: GTK IE in unencrypted key data"); 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie.gtk == NULL) { 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: No GTK IE in Group Key msg 1/2"); 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt maxkeylen = gd->gtk_len = ie.gtk_len - 2; 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher, 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd->gtk_len, maxkeylen, 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &gd->key_rsc_len, &gd->alg)) 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: received GTK in group key handshake", 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie.gtk, ie.gtk_len); 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd->keyidx = ie.gtk[0] & 0x3; 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd->tx = wpa_supplicant_gtk_tx_bit_workaround(sm, 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !!(ie.gtk[0] & BIT(2))); 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie.gtk_len - 2 > sizeof(gd->gtk)) { 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: Too long GTK in GTK IE (len=%lu)", 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) ie.gtk_len - 2); 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(gd->gtk, ie.gtk + 2, ie.gtk_len - 2); 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ieee80211w_set_keys(sm, &ie) < 0) 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: Failed to configure IGTK"); 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm, 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t keydatalen, int key_info, 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t extra_len, u16 ver, 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_gtk_data *gd) 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t maxkeylen; 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ek[32]; 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd->gtk_len = WPA_GET_BE16(key->key_length); 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt maxkeylen = keydatalen; 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keydatalen > extra_len) { 12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Truncated EAPOL-Key packet: " 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "key_data_length=%lu > extra_len=%lu", 12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) keydatalen, (unsigned long) extra_len); 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (maxkeylen < 8) { 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Too short maxkeylen (%lu)", 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) maxkeylen); 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt maxkeylen -= 8; 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher, 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd->gtk_len, maxkeylen, 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &gd->key_rsc_len, &gd->alg)) 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd->keyidx = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >> 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_KEY_INDEX_SHIFT; 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) { 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ek, key->key_iv, 16); 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ek + 16, sm->ptk.kek, 16); 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keydatalen > sizeof(gd->gtk)) { 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: RC4 key data too long (%lu)", 12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) keydatalen); 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(gd->gtk, key + 1, keydatalen); 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rc4_skip(ek, 32, 256, gd->gtk, keydatalen)) { 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: RC4 failed"); 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keydatalen % 8) { 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Unsupported AES-WRAP len %lu", 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) keydatalen); 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (maxkeylen > sizeof(gd->gtk)) { 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: AES-WRAP key data " 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "too long (keydatalen=%lu maxkeylen=%lu)", 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) keydatalen, 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) maxkeylen); 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (aes_unwrap(sm->ptk.kek, maxkeylen / 8, 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (const u8 *) (key + 1), gd->gtk)) { 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: AES unwrap failed - could not decrypt " 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "GTK"); 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Unsupported key_info type %d", ver); 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gd->tx = wpa_supplicant_gtk_tx_bit_workaround( 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, !!(key_info & WPA_KEY_INFO_TXRX)); 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_send_2_of_2(struct wpa_sm *sm, 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ver, u16 key_info) 12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rlen; 12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *reply; 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rbuf; 12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, 12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(*reply), &rlen, (void *) &reply); 12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) 12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply->type = sm->proto == WPA_PROTO_RSN ? 12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; 12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info &= WPA_KEY_INFO_KEY_INDEX_MASK; 12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info |= ver | WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE; 12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_info, key_info); 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->proto == WPA_PROTO_RSN) 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_length, 0); 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply->key_length, key->key_length, 2); 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply->replay_counter, key->replay_counter, 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_data_length, 0); 12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/2"); 13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_send(sm, sm->ptk.kck, ver, sm->bssid, ETH_P_EAPOL, 13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf, rlen, reply->key_mic); 13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_1_of_2(struct wpa_sm *sm, 13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, 13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int extra_len, u16 ver) 13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info, keydatalen; 13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int rekey, ret; 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_gtk_data gd; 13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&gd, 0, sizeof(gd)); 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rekey = wpa_sm_get_state(sm) == WPA_COMPLETED; 13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of Group Key " 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver); 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = WPA_GET_BE16(key->key_info); 13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keydatalen = WPA_GET_BE16(key->key_data_length); 13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->proto == WPA_PROTO_RSN) { 13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = wpa_supplicant_process_1_of_2_rsn(sm, 13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (const u8 *) (key + 1), 13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keydatalen, key_info, 13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &gd); 13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = wpa_supplicant_process_1_of_2_wpa(sm, key, keydatalen, 13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info, extra_len, 13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver, &gd); 13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE); 13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_install_gtk(sm, &gd, key->key_rsc) || 13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_send_2_of_2(sm, key, ver, key_info)) 13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rekey) { 13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Group rekeying " 13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "completed with " MACSTR " [GTK=%s]", 13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(sm->bssid), wpa_cipher_txt(sm->group_cipher)); 13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_cancel_auth_timeout(sm); 13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_set_state(sm, WPA_COMPLETED); 13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_key_neg_complete(sm, sm->bssid, 13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info & 13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_SECURE); 13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1356cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 1357cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_sm_set_rekey_offload(sm); 1358cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfailed: 13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); 13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm, 13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *key, 13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 ver, 13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mic[16]; 13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ok = 0; 13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(mic, key->key_mic, 16); 13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->tptk_set) { 13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(key->key_mic, 0, 16); 13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_mic(sm->tptk.kck, ver, buf, len, 13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_mic); 13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(mic, key->key_mic, 16) != 0) { 13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Invalid EAPOL-Key MIC " 13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "when using TPTK - ignoring TPTK"); 13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ok = 1; 13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->tptk_set = 0; 13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ptk_set = 1; 13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk)); 13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ok && sm->ptk_set) { 13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(key->key_mic, 0, 16); 13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_mic(sm->ptk.kck, ver, buf, len, 13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_mic); 13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(mic, key->key_mic, 16) != 0) { 13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Invalid EAPOL-Key MIC - " 13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dropping packet"); 13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ok = 1; 14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ok) { 14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Could not verify EAPOL-Key MIC - " 14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dropping packet"); 14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->rx_replay_counter, key->replay_counter, 14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->rx_replay_counter_set = 1; 14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */ 14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm, 14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *key, u16 ver) 14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 keydatalen = WPA_GET_BE16(key->key_data_length); 14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data", 14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) (key + 1), keydatalen); 14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->ptk_set) { 14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: PTK not available, cannot decrypt EAPOL-Key Key " 14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Data"); 14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Decrypt key data here so that this operation does not need 14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to be implemented separately for each message type. */ 14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) { 14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ek[32]; 14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ek, key->key_iv, 16); 14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ek + 16, sm->ptk.kek, 16); 14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rc4_skip(ek, 32, 256, (u8 *) (key + 1), keydatalen)) { 14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, 14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: RC4 failed"); 14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || 14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver == WPA_KEY_INFO_TYPE_AES_128_CMAC) { 14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf; 14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keydatalen % 8) { 14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Unsupported AES-WRAP len %d", 14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keydatalen); 14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keydatalen -= 8; /* AES-WRAP adds 8 bytes */ 14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_malloc(keydatalen); 14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: No memory for AES-UNWRAP buffer"); 14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (aes_unwrap(sm->ptk.kek, keydatalen / 8, 14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) (key + 1), buf)) { 14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: AES unwrap failed - " 14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "could not decrypt EAPOL-Key key data"); 14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key + 1, buf, keydatalen); 14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(key->key_data_length, keydatalen); 14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Unsupported key_info type %d", ver); 14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPA: decrypted EAPOL-Key key data", 14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) (key + 1), keydatalen); 14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_aborted_cached - Notify WPA that PMKSA caching was aborted 14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_aborted_cached(struct wpa_sm *sm) 14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm && sm->cur_pmksa) { 14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: Cancelling PMKSA caching attempt"); 14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->cur_pmksa = NULL; 14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_eapol_key_dump(struct wpa_sm *sm, 14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key) 14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_STDOUT_DEBUG 15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info = WPA_GET_BE16(key->key_info); 15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, " EAPOL-Key type=%d", key->type); 15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " key_info 0x%x (ver=%d keyidx=%d rsvd=%d %s%s%s%s%s%s%s%s)", 15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info, key_info & WPA_KEY_INFO_TYPE_MASK, 15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >> 15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_KEY_INDEX_SHIFT, 15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (key_info & (BIT(13) | BIT(14) | BIT(15))) >> 13, 15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info & WPA_KEY_INFO_KEY_TYPE ? "Pairwise" : "Group", 15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info & WPA_KEY_INFO_INSTALL ? " Install" : "", 15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info & WPA_KEY_INFO_ACK ? " Ack" : "", 15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info & WPA_KEY_INFO_MIC ? " MIC" : "", 15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info & WPA_KEY_INFO_SECURE ? " Secure" : "", 15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info & WPA_KEY_INFO_ERROR ? " Error" : "", 15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info & WPA_KEY_INFO_REQUEST ? " Request" : "", 15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info & WPA_KEY_INFO_ENCR_KEY_DATA ? " Encr" : ""); 15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " key_length=%u key_data_length=%u", 15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_BE16(key->key_length), 15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_BE16(key->key_data_length)); 15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, " replay_counter", 15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->replay_counter, WPA_REPLAY_COUNTER_LEN); 15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, " key_nonce", key->key_nonce, WPA_NONCE_LEN); 15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, " key_iv", key->key_iv, 16); 15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, " key_rsc", key->key_rsc, 8); 15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, " key_id (reserved)", key->key_id, 8); 15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, " key_mic", key->key_mic, 16); 15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_STDOUT_DEBUG */ 15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_rx_eapol - Process received WPA EAPOL frames 15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @src_addr: Source MAC address of the EAPOL packet 15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Pointer to the beginning of the EAPOL data (EAPOL header) 15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Length of the EAPOL frame 15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 = WPA EAPOL-Key processed, 0 = not a WPA EAPOL-Key, -1 failure 15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called for each received EAPOL frame. Other than EAPOL-Key 15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * frames can be skipped if filtering is done elsewhere. wpa_sm_rx_eapol() is 15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * only processing WPA and WPA2 EAPOL-Key frames. 15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The received EAPOL-Key packets are validated and valid packets are replied 15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to. In addition, key material (PTK, GTK) is configured at the end of a 15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * successful key handshake. 15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, 15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t plen, data_len, extra_len; 15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee802_1x_hdr *hdr; 15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *key; 15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info, ver; 15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *tmp; 15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = -1; 15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey = NULL; 15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ft_completed = 0; 15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < sizeof(*hdr) + sizeof(*key)) { 15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: EAPOL frame too short to be a WPA " 15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAPOL-Key (len %lu, expecting at least %lu)", 15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len, 15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) sizeof(*hdr) + sizeof(*key)); 15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = os_malloc(len); 15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tmp == NULL) 15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(tmp, buf, len); 15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct ieee802_1x_hdr *) tmp; 15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = (struct wpa_eapol_key *) (hdr + 1); 15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = be_to_host16(hdr->length); 15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data_len = plen + sizeof(*hdr); 15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "IEEE 802.1X RX: version=%d type=%d length=%lu", 15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->version, hdr->type, (unsigned long) plen); 15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr->version < EAPOL_VERSION) { 15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: backwards compatibility */ 15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr->type != IEEE802_1X_TYPE_EAPOL_KEY) { 15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: EAPOL frame (type %u) discarded, " 15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not a Key frame", hdr->type); 15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (plen > len - sizeof(*hdr) || plen < sizeof(*key)) { 15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: EAPOL frame payload size %lu " 15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "invalid (frame size %lu)", 15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) plen, (unsigned long) len); 16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN) 16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: EAPOL-Key type (%d) unknown, discarded", 16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->type); 16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_dump(sm, key); 16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_notify_lower_layer_success(sm->eapol, 0); 16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL-Key", tmp, len); 16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data_len < len) { 16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: ignoring %lu bytes after the IEEE 802.1X data", 16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len - data_len); 16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = WPA_GET_BE16(key->key_info); 16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = key_info & WPA_KEY_INFO_TYPE_MASK; 16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && 16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W) 16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver != WPA_KEY_INFO_TYPE_AES_128_CMAC && 16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */ 16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { 16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Unsupported EAPOL-Key descriptor version %d", 16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver); 16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->key_mgmt)) { 16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* IEEE 802.11r uses a new key_info type (AES-128-CMAC). */ 16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { 16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FT: AP did not use AES-128-CMAC"); 16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_sha256(sm->key_mgmt)) { 16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { 16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: AP did not use the " 16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "negotiated AES-128-CMAC"); 16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pairwise_cipher == WPA_CIPHER_CCMP && 16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { 16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: CCMP is used, but EAPOL-Key " 16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "descriptor version (%d) is not 2", ver); 16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->group_cipher != WPA_CIPHER_CCMP && 16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(key_info & WPA_KEY_INFO_KEY_TYPE)) { 16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Earlier versions of IEEE 802.11i did not explicitly 16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * require version 2 descriptor for all EAPOL-Key 16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * packets, so allow group keys to use version 1 if 16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * CCMP is not used for them. */ 16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Backwards compatibility: allow invalid " 16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "version for non-CCMP group keys"); 16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 167161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->pairwise_cipher == WPA_CIPHER_GCMP && 167261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { 167361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 167461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "WPA: GCMP is used, but EAPOL-Key " 167561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "descriptor version (%d) is not 2", ver); 167661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt goto out; 167761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { 16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peerkey->addr, src_addr, ETH_ALEN) == 0) 16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(key_info & WPA_KEY_INFO_SMK_MESSAGE) && peerkey) { 16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!peerkey->initiator && peerkey->replay_counter_set && 16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(key->replay_counter, peerkey->replay_counter, 16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN) <= 0) { 16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: EAPOL-Key Replay Counter did not " 16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "increase (STK) - dropping packet"); 16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (peerkey->initiator) { 16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 _tmp[WPA_REPLAY_COUNTER_LEN]; 16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(_tmp, key->replay_counter, 16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(_tmp, WPA_REPLAY_COUNTER_LEN); 16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(_tmp, peerkey->replay_counter, 16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN) != 0) { 17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: EAPOL-Key Replay " 17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Counter did not match (STK) - " 17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dropping packet"); 17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey && peerkey->initiator && (key_info & WPA_KEY_INFO_ACK)) { 17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: Ack bit in key_info from STK peer"); 17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!peerkey && sm->rx_replay_counter_set && 17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(key->replay_counter, sm->rx_replay_counter, 17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN) <= 0) { 17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: EAPOL-Key Replay Counter did not increase - " 17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dropping packet"); 17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(key_info & (WPA_KEY_INFO_ACK | WPA_KEY_INFO_SMK_MESSAGE)) 17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt && (peerkey == NULL || !peerkey->initiator) 17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ) { 17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: No Ack bit in key_info"); 17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_REQUEST) { 17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: EAPOL-Key with Request bit - dropped"); 17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((key_info & WPA_KEY_INFO_MIC) && !peerkey && 17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_verify_eapol_key_mic(sm, key, ver, tmp, data_len)) 17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((key_info & WPA_KEY_INFO_MIC) && peerkey && 17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey_verify_eapol_key_mic(sm, peerkey, key, ver, tmp, data_len)) 17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt extra_len = data_len - sizeof(*hdr) - sizeof(*key); 17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (WPA_GET_BE16(key->key_data_length) > extra_len) { 17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Invalid EAPOL-Key " 17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "frame - key_data overflow (%d > %lu)", 17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_BE16(key->key_data_length), 17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) extra_len); 17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt extra_len = WPA_GET_BE16(key->key_data_length); 17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->proto == WPA_PROTO_RSN && 17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { 17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_decrypt_key_data(sm, key, ver)) 17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt extra_len = WPA_GET_BE16(key->key_data_length); 17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_KEY_TYPE) { 17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) { 17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Ignored EAPOL-Key (Pairwise) with " 17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "non-zero key index"); 17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey) { 17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* PeerKey 4-Way Handshake */ 17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey_rx_eapol_4way(sm, peerkey, key, key_info, ver); 17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_info & WPA_KEY_INFO_MIC) { 17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3/4 4-Way Handshake */ 17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_process_3_of_4(sm, key, ver); 17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1/4 4-Way Handshake */ 17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_process_1_of_4(sm, src_addr, key, 17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver); 17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) { 17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* PeerKey SMK Handshake */ 17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey_rx_eapol_smk(sm, src_addr, key, extra_len, key_info, 17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver); 17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_MIC) { 17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1/2 Group Key Handshake */ 17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_process_1_of_2(sm, src_addr, key, 17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt extra_len, ver); 17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: EAPOL-Key (Group) without Mic bit - " 17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dropped"); 18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 1; 18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtout: 18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(tmp); 18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE 18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u32 wpa_key_mgmt_suite(struct wpa_sm *sm) 18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (sm->key_mgmt) { 18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_IEEE8021X: 18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return (sm->proto == WPA_PROTO_RSN ? 18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_AUTH_KEY_MGMT_UNSPEC_802_1X : 18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_AUTH_KEY_MGMT_UNSPEC_802_1X); 18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_PSK: 18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return (sm->proto == WPA_PROTO_RSN ? 18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X : 18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X); 18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_FT_IEEE8021X: 18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return RSN_AUTH_KEY_MGMT_FT_802_1X; 18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_FT_PSK: 18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return RSN_AUTH_KEY_MGMT_FT_PSK; 18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_IEEE8021X_SHA256: 18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return RSN_AUTH_KEY_MGMT_802_1X_SHA256; 18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_PSK_SHA256: 18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return RSN_AUTH_KEY_MGMT_PSK_SHA256; 18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 1835d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt case WPA_KEY_MGMT_CCKM: 1836d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return (sm->proto == WPA_PROTO_RSN ? 1837d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt RSN_AUTH_KEY_MGMT_CCKM: 1838d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt WPA_AUTH_KEY_MGMT_CCKM); 18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_WPA_NONE: 18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_AUTH_KEY_MGMT_NONE; 18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RSN_SUITE "%02x-%02x-%02x-%d" 18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RSN_SUITE_ARG(s) \ 18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff 18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_get_mib - Dump text list of MIB entries 18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Buffer for the list 18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buflen: Length of the buffer 18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Number of bytes written to buffer 18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used fetch dot11 MIB variables. 18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen) 18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char pmkid_txt[PMKID_LEN * 2 + 1]; 18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int rsna, ret; 18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 18658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->cur_pmksa) { 18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt), 18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->cur_pmksa->pmkid, PMKID_LEN); 18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmkid_txt[0] = '\0'; 18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((wpa_key_mgmt_wpa_psk(sm->key_mgmt) || 18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) && 18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->proto == WPA_PROTO_RSN) 18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsna = 1; 18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsna = 0; 18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf, buflen, 18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAOptionImplemented=TRUE\n" 18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAPreauthenticationImplemented=TRUE\n" 18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAEnabled=%s\n" 18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAPreauthenticationEnabled=%s\n" 18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigVersion=%d\n" 18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigPairwiseKeysSupported=5\n" 18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigGroupCipherSize=%d\n" 18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigPMKLifetime=%d\n" 18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigPMKReauthThreshold=%d\n" 18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigNumberOfPTKSAReplayCounters=1\n" 18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigSATimeout=%d\n", 18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsna ? "TRUE" : "FALSE", 18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsna ? "TRUE" : "FALSE", 18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_VERSION, 18944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_cipher_key_len(sm->group_cipher) * 8, 18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAConfigPMKLifetime, 18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAConfigPMKReauthThreshold, 18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAConfigSATimeout); 18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || (size_t) ret >= buflen) 18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = ret; 19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf( 19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf + len, buflen - len, 19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n" 19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n" 19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n" 19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAPMKIDUsed=%s\n" 19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n" 19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n" 19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n" 19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n" 19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNA4WayHandshakeFailures=%u\n", 19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)), 19144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto, 19154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->pairwise_cipher)), 19164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto, 19174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->group_cipher)), 19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmkid_txt, 19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)), 19204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto, 19214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->pairwise_cipher)), 19224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto, 19234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->group_cipher)), 19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNA4WayHandshakeFailures); 19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret >= 0 && (size_t) ret < buflen) 19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return (int) len; 19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE */ 19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_sm_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry, 1934d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt void *ctx, enum pmksa_free_reason reason) 19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm = ctx; 1937d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt int deauth = 0; 1938d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 1939d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA cache entry free_cb: " 1940d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt MACSTR " reason=%d", MAC2STR(entry->aa), reason); 1941d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 1942d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (sm->cur_pmksa == entry) { 1943d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 1944d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt "RSN: %s current PMKSA entry", 1945d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt reason == PMKSA_REPLACE ? "replaced" : "removed"); 1946d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt pmksa_cache_clear_current(sm); 1947d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 1948d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt /* 1949d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * If an entry is simply being replaced, there's no need to 1950d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * deauthenticate because it will be immediately re-added. 1951d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * This happens when EAP authentication is completed again 1952d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * (reauth or failed PMKSA caching attempt). 1953d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt */ 1954d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (reason != PMKSA_REPLACE) 1955d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt deauth = 1; 1956d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1958d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (reason == PMKSA_EXPIRE && 19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (sm->pmk_len == entry->pmk_len && 19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(sm->pmk, entry->pmk, sm->pmk_len) == 0)) { 19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 1962d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt "RSN: deauthenticating due to expired PMK"); 1963d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt pmksa_cache_clear_current(sm); 1964d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt deauth = 1; 1965d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1967d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (deauth) { 19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(sm->pmk, 0, sizeof(sm->pmk)); 19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); 19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_init - Initialize WPA state machine 19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ctx: Context pointer for callbacks; this needs to be an allocated buffer 19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the allocated WPA state machine data 19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to allocate a new WPA state machine and the returned 19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * value is passed to all WPA state machine calls. 19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx) 19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm; 19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm = os_zalloc(sizeof(*sm)); 19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_init(&sm->pmksa_candidates); 19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->renew_snonce = 1; 19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ctx = ctx; 19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAConfigPMKLifetime = 43200; 19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAConfigPMKReauthThreshold = 70; 19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAConfigSATimeout = 60; 19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmksa = pmksa_cache_init(wpa_sm_pmksa_free_cb, sm, sm); 19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pmksa == NULL) { 19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, 20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: PMKSA cache initialization failed"); 20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm); 20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm; 20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_deinit - Deinitialize WPA state machine 20118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_deinit(struct wpa_sm *sm) 20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_cache_deinit(sm->pmksa); 20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_sm_start_preauth, sm, NULL); 20198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL); 20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->assoc_wpa_ie); 20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->ap_wpa_ie); 20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->ap_rsn_ie); 20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->ctx); 20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey_deinit(sm); 20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->assoc_resp_ies); 20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm); 20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_notify_assoc - Notify WPA state machine about association 20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @bssid: The BSSID of the new association 20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called to let WPA state machine know that the connection 20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * was established. 20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid) 20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int clear_ptk = 1; 20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Association event - clear replay counter"); 20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->bssid, bssid, ETH_ALEN); 20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(sm->rx_replay_counter, 0, WPA_REPLAY_COUNTER_LEN); 20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->rx_replay_counter_set = 0; 20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->renew_snonce = 1; 20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(sm->preauth_bssid, bssid, ETH_ALEN) == 0) 20548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_deinit(sm); 20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_ft_is_completed(sm)) { 20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 20598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Clear portValid to kick EAPOL state machine to re-enter 20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AUTHENTICATED state to get the EAPOL port Authorized. 20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_notify_portValid(sm->eapol, FALSE); 20638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_key_neg_complete(sm, sm->bssid, 1); 20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Prepare for the next transition */ 20668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ft_prepare_auth_request(sm, NULL); 20678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt clear_ptk = 0; 20698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (clear_ptk) { 20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 20748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE 802.11, 8.4.10: Delete PTK SA on (re)association if 20758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * this is not part of a Fast BSS Transition. 20768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 20778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PTK"); 20788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ptk_set = 0; 20798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->tptk_set = 0; 20808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS 20838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_assoc(sm); 20848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS */ 20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 20898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_notify_disassoc - Notify WPA state machine about disassociation 20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 20928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called to let WPA state machine know that the connection 20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * was lost. This will abort any existing pre-authentication session. 20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_notify_disassoc(struct wpa_sm *sm) 20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_deinit(sm); 2098d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt pmksa_cache_clear_current(sm); 20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_get_state(sm) == WPA_4WAY_HANDSHAKE) 21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNA4WayHandshakeFailures++; 21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS 21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_disassoc(sm); 21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS */ 21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_pmk - Set PMK 21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmk: The new PMK 21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmk_len: The length of the new PMK in bytes 21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 21138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Configure the PMK for WPA state machine. 21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len) 21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmk_len = pmk_len; 21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->pmk, pmk, pmk_len); 21228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Set XXKey to be PSK for FT key derivation */ 21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->xxkey_len = pmk_len; 21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->xxkey, pmk, pmk_len); 21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 21328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_pmk_from_pmksa - Set PMK based on the current PMKSA 21338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 21348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 21358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Take the PMK from the current PMKSA into use. If no PMKSA is active, the PMK 21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * will be cleared. 21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 21388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm) 21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->cur_pmksa) { 21448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmk_len = sm->cur_pmksa->pmk_len; 21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->pmk, sm->cur_pmksa->pmk, sm->pmk_len); 21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmk_len = PMK_LEN; 21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(sm->pmk, 0, PMK_LEN); 21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_fast_reauth - Set fast reauthentication (EAP) enabled/disabled 21558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 21568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @fast_reauth: Whether fast reauthentication (EAP) is allowed 21578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 21588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth) 21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm) 21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->fast_reauth = fast_reauth; 21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_scard_ctx - Set context pointer for smartcard callbacks 21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 21688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @scard_ctx: Context pointer for smartcard related callback functions 21698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx) 21718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 21728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 21738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 21748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->scard_ctx = scard_ctx; 21758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->preauth_eapol) 21768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_register_scard_ctx(sm->preauth_eapol, scard_ctx); 21778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 21818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_config - Notification of current configration change 21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 21838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config: Pointer to current network configuration 21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Notify WPA state machine that configuration has changed. config will be 21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * stored as a backpointer to network configuration. This can be %NULL to clear 21878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the stored pointed. 21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 21898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config) 21908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm) 21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (config) { 21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->network_ctx = config->network_ctx; 21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->peerkey_enabled = config->peerkey_enabled; 21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->allowed_pairwise_cipher = config->allowed_pairwise_cipher; 21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->proactive_key_caching = config->proactive_key_caching; 21998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_workaround = config->eap_workaround; 22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_conf_ctx = config->eap_conf_ctx; 22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (config->ssid) { 22028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->ssid, config->ssid, config->ssid_len); 22038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ssid_len = config->ssid_len; 22048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ssid_len = 0; 22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ptk_rekey = config->wpa_ptk_rekey; 22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->network_ctx = NULL; 22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->peerkey_enabled = 0; 22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->allowed_pairwise_cipher = 0; 22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->proactive_key_caching = 0; 22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_workaround = 0; 22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_conf_ctx = NULL; 22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ssid_len = 0; 22158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ptk_rekey = 0; 22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 22188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 22218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_own_addr - Set own MAC address 22228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 22238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: Own MAC address 22248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 22258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_own_addr(struct wpa_sm *sm, const u8 *addr) 22268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 22278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm) 22288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->own_addr, addr, ETH_ALEN); 22298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 22308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 22338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_ifname - Set network interface name 22348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 22358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ifname: Interface name 22368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @bridge_ifname: Optional bridge interface name (for pre-auth) 22378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 22388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_ifname(struct wpa_sm *sm, const char *ifname, 22398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *bridge_ifname) 22408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 22418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm) { 22428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ifname = ifname; 22438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->bridge_ifname = bridge_ifname; 22448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 22468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 22498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_eapol - Set EAPOL state machine pointer 22508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 22518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eapol: Pointer to EAPOL state machine allocated with eapol_sm_init() 22528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_eapol(struct wpa_sm *sm, struct eapol_sm *eapol) 22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm) 22568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eapol = eapol; 22578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 22588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 22618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_param - Set WPA state machine parameters 22628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 22638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @param: Parameter field 22648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @value: Parameter value 22658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 22668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 22678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, 22688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int value) 22698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 22708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 22718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 22738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 22748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (param) { 22768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RSNA_PMK_LIFETIME: 22778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (value > 0) 22788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAConfigPMKLifetime = value; 22798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 22818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 22828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RSNA_PMK_REAUTH_THRESHOLD: 22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (value > 0 && value <= 100) 22848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAConfigPMKReauthThreshold = value; 22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 22888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RSNA_SA_TIMEOUT: 22898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (value > 0) 22908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAConfigSATimeout = value; 22918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 22928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 22938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PARAM_PROTO: 22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->proto = value; 22968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PARAM_PAIRWISE: 22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pairwise_cipher = value; 22998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PARAM_GROUP: 23018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group_cipher = value; 23028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PARAM_KEY_MGMT: 23048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->key_mgmt = value; 23058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 23078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PARAM_MGMT_GROUP: 23088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->mgmt_group_cipher = value; 23098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 23118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PARAM_RSN_ENABLED: 23128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->rsn_enabled = value; 23138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PARAM_MFP: 23158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->mfp = value; 23168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 23188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 23228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 23268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_get_param - Get WPA state machine parameters 23278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 23288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @param: Parameter field 23298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Parameter value 23308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 23318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned int wpa_sm_get_param(struct wpa_sm *sm, enum wpa_sm_conf_params param) 23328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 23348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 23358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (param) { 23378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RSNA_PMK_LIFETIME: 23388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->dot11RSNAConfigPMKLifetime; 23398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RSNA_PMK_REAUTH_THRESHOLD: 23408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->dot11RSNAConfigPMKReauthThreshold; 23418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RSNA_SA_TIMEOUT: 23428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->dot11RSNAConfigSATimeout; 23438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PARAM_PROTO: 23448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->proto; 23458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PARAM_PAIRWISE: 23468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->pairwise_cipher; 23478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PARAM_GROUP: 23488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->group_cipher; 23498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PARAM_KEY_MGMT: 23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->key_mgmt; 23518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PARAM_MGMT_GROUP: 23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->mgmt_group_cipher; 23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PARAM_RSN_ENABLED: 23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->rsn_enabled; 23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 23648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_get_status - Get WPA state machine 23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 23668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Buffer for status information 23678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buflen: Maximum buffer length 23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @verbose: Whether to include verbose status information 23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Number of bytes written to buf. 23708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 23718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Query WPA state machine for status information. This function fills in 23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * a text area with current status information. If the buffer (buf) is not 23738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * large enough, status information will be truncated to fit the buffer. 23748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 23758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen, 23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int verbose) 23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *pos = buf, *end = buf + buflen; 23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 23808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(pos, end - pos, 23828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pairwise_cipher=%s\n" 23838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "group_cipher=%s\n" 23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "key_mgmt=%s\n", 23858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_cipher_txt(sm->pairwise_cipher), 23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_cipher_txt(sm->group_cipher), 23878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_key_mgmt_txt(sm->key_mgmt, sm->proto)); 23888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || ret >= end - pos) 23898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos - buf; 23908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ret; 2391d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 2392d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (sm->mfp != NO_MGMT_FRAME_PROTECTION && sm->ap_rsn_ie) { 2393d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt struct wpa_ie_data rsn; 2394d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn) 2395d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt >= 0 && 2396d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt rsn.capabilities & (WPA_CAPABILITY_MFPR | 2397d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt WPA_CAPABILITY_MFPC)) { 2398d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt ret = os_snprintf(pos, end - pos, "pmf=%d\n", 2399d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt (rsn.capabilities & 2400d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt WPA_CAPABILITY_MFPR) ? 2 : 1); 2401d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (ret < 0 || ret >= end - pos) 2402d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return pos - buf; 2403d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt pos += ret; 2404d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 2405d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 2406d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 24078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos - buf; 24088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 24098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2411f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidtint wpa_sm_pmf_enabled(struct wpa_sm *sm) 2412f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt{ 2413f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt struct wpa_ie_data rsn; 2414f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt 2415f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt if (sm->mfp == NO_MGMT_FRAME_PROTECTION || !sm->ap_rsn_ie) 2416f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt return 0; 2417f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt 2418f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn) >= 0 && 2419f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt rsn.capabilities & (WPA_CAPABILITY_MFPR | WPA_CAPABILITY_MFPC)) 2420f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt return 1; 2421f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt 2422f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt return 0; 2423f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt} 2424f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt 2425f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt 24268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 24278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_assoc_wpa_ie_default - Generate own WPA/RSN IE from configuration 24288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 24298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_ie: Pointer to buffer for WPA/RSN IE 24308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_ie_len: Pointer to the length of the wpa_ie buffer 24318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 24328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 24338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie, 24348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t *wpa_ie_len) 24358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 24368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 24378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 24398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 24408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wpa_gen_wpa_ie(sm, wpa_ie, *wpa_ie_len); 24428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) 24438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 24448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *wpa_ie_len = res; 24458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Set own WPA IE default", 24478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ie, *wpa_ie_len); 24488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->assoc_wpa_ie == NULL) { 24508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 24518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Make a copy of the WPA/RSN IE so that 4-Way Handshake gets 24528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the correct version of the IE even if PMKSA caching is 24538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * aborted (which would remove PMKID from IE generation). 24548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 24558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->assoc_wpa_ie = os_malloc(*wpa_ie_len); 24568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->assoc_wpa_ie == NULL) 24578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 24588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->assoc_wpa_ie, wpa_ie, *wpa_ie_len); 24608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->assoc_wpa_ie_len = *wpa_ie_len; 24618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 24648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 24658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 24688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_assoc_wpa_ie - Set own WPA/RSN IE from (Re)AssocReq 24698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 24708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ie: Pointer to IE data (starting from id) 24718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: IE length 24728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 24738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 24748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Inform WPA state machine about the WPA/RSN IE used in (Re)Association 24758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Request frame. The IE will be used to override the default value generated 24768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * with wpa_sm_set_assoc_wpa_ie_default(). 24778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 24788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_set_assoc_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len) 24798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 24808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 24818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 24828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->assoc_wpa_ie); 24848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie == NULL || len == 0) { 24858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 24868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: clearing own WPA/RSN IE"); 24878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->assoc_wpa_ie = NULL; 24888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->assoc_wpa_ie_len = 0; 24898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 24908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: set own WPA/RSN IE", ie, len); 24918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->assoc_wpa_ie = os_malloc(len); 24928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->assoc_wpa_ie == NULL) 24938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 24948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->assoc_wpa_ie, ie, len); 24968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->assoc_wpa_ie_len = len; 24978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 25008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 25018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 25048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_ap_wpa_ie - Set AP WPA IE from Beacon/ProbeResp 25058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 25068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ie: Pointer to IE data (starting from id) 25078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: IE length 25088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 25098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 25108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Inform WPA state machine about the WPA IE used in Beacon / Probe Response 25118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * frame. 25128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 25138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len) 25148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 25158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 25168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 25178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->ap_wpa_ie); 25198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie == NULL || len == 0) { 25208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 25218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: clearing AP WPA IE"); 25228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ap_wpa_ie = NULL; 25238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ap_wpa_ie_len = 0; 25248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 25258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: set AP WPA IE", ie, len); 25268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ap_wpa_ie = os_malloc(len); 25278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->ap_wpa_ie == NULL) 25288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 25298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->ap_wpa_ie, ie, len); 25318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ap_wpa_ie_len = len; 25328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 25358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 25368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 25398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_ap_rsn_ie - Set AP RSN IE from Beacon/ProbeResp 25408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 25418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ie: Pointer to IE data (starting from id) 25428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: IE length 25438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 25448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 25458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Inform WPA state machine about the RSN IE used in Beacon / Probe Response 25468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * frame. 25478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 25488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len) 25498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 25508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 25518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 25528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->ap_rsn_ie); 25548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie == NULL || len == 0) { 25558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 25568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: clearing AP RSN IE"); 25578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ap_rsn_ie = NULL; 25588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ap_rsn_ie_len = 0; 25598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 25608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: set AP RSN IE", ie, len); 25618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ap_rsn_ie = os_malloc(len); 25628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->ap_rsn_ie == NULL) 25638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 25648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->ap_rsn_ie, ie, len); 25668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ap_rsn_ie_len = len; 25678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 25708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 25718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 25748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_parse_own_wpa_ie - Parse own WPA/RSN IE 25758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 25768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Pointer to data area for parsing results 25778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 if IE is not known, or -2 on parsing failure 25788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 25798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Parse the contents of the own WPA or RSN IE from (Re)AssocReq and write the 25808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * parsed data into data. 25818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 25828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, struct wpa_ie_data *data) 25838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 25848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 25858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 25868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->assoc_wpa_ie == NULL) { 25888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 25898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: No WPA/RSN IE available from association info"); 25908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 25918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_parse_wpa_ie(sm->assoc_wpa_ie, sm->assoc_wpa_ie_len, data)) 25938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -2; 25948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 25958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 25968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len) 25998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pmksa_cache_list(sm->pmksa, buf, len); 26018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_drop_sa(struct wpa_sm *sm) 26058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PMK and PTK"); 26078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ptk_set = 0; 26088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->tptk_set = 0; 26098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(sm->pmk, 0, sizeof(sm->pmk)); 26108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&sm->ptk, 0, sizeof(sm->ptk)); 26118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&sm->tptk, 0, sizeof(sm->tptk)); 26128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_has_ptk(struct wpa_sm *sm) 26168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 26188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 26198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->ptk_set; 26208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid wpa_sm_update_replay_ctr(struct wpa_sm *sm, const u8 *replay_ctr) 26241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 26251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(sm->rx_replay_counter, replay_ctr, WPA_REPLAY_COUNTER_LEN); 26261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 26271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid wpa_sm_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx) 26301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 2631f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt pmksa_cache_flush(sm->pmksa, network_ctx, NULL, 0); 26321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 263361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 263461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2635a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#ifdef CONFIG_WNM 263661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf) 263761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 263861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_gtk_data gd; 263961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_IEEE80211W 264061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_igtk_kde igd; 264161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u16 keyidx; 264261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 264361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u16 keyinfo; 264461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 keylen; /* plaintext key len */ 264561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 *key_rsc; 264661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 264761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_memset(&gd, 0, sizeof(gd)); 264861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_IEEE80211W 264961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_memset(&igd, 0, sizeof(igd)); 265061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 265161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 26524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt keylen = wpa_cipher_key_len(sm->group_cipher); 26534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt gd.key_rsc_len = wpa_cipher_rsc_len(sm->group_cipher); 26544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt gd.alg = wpa_cipher_to_alg(sm->group_cipher); 26554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (gd.alg == WPA_ALG_NONE) { 265661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "Unsupported group cipher suite"); 265761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 265861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 265961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 266061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (subelem_id == WNM_SLEEP_SUBELEM_GTK) { 266161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt key_rsc = buf + 5; 2662a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt keyinfo = WPA_GET_LE16(buf + 2); 266361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gd.gtk_len = keylen; 266461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (gd.gtk_len != buf[4]) { 266561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "GTK len mismatch len %d vs %d", 266661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gd.gtk_len, buf[4]); 266761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 266861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 266961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gd.keyidx = keyinfo & 0x03; /* B0 - B1 */ 267061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gd.tx = wpa_supplicant_gtk_tx_bit_workaround( 267161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sm, !!(keyinfo & WPA_KEY_INFO_TXRX)); 267261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2673a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt os_memcpy(gd.gtk, buf + 13, gd.gtk_len); 267461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 267561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "Install GTK (WNM SLEEP)", 267661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gd.gtk, gd.gtk_len); 267761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_supplicant_install_gtk(sm, &gd, key_rsc)) { 267861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to install the GTK in " 267961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "WNM mode"); 268061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 268161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 268261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_IEEE80211W 268361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else if (subelem_id == WNM_SLEEP_SUBELEM_IGTK) { 268461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_memcpy(igd.keyid, buf + 2, 2); 268561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_memcpy(igd.pn, buf + 4, 6); 268661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 268761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt keyidx = WPA_GET_LE16(igd.keyid); 2688a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt os_memcpy(igd.igtk, buf + 10, WPA_IGTK_LEN); 268961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 269061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "Install IGTK (WNM SLEEP)", 269161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt igd.igtk, WPA_IGTK_LEN); 269261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_sm_set_key(sm, WPA_ALG_IGTK, broadcast_ether_addr, 269361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt keyidx, 0, igd.pn, sizeof(igd.pn), 269461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt igd.igtk, WPA_IGTK_LEN) < 0) { 269561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to install the IGTK in " 269661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "WNM mode"); 269761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 269861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 269961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 270061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else { 270161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "Unknown element id"); 270261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 270361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 270461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 270561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 270661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 2707a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#endif /* CONFIG_WNM */ 2708