1189251Ssam/* 2189251Ssam * WPA Supplicant - WPA state machine and EAPOL-Key processing 3252726Srpaulo * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi> 4189251Ssam * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7189251Ssam */ 8189251Ssam 9189251Ssam#include "includes.h" 10189251Ssam 11189251Ssam#include "common.h" 12214734Srpaulo#include "crypto/aes_wrap.h" 13214734Srpaulo#include "crypto/crypto.h" 14252726Srpaulo#include "crypto/random.h" 15214734Srpaulo#include "common/ieee802_11_defs.h" 16214734Srpaulo#include "eapol_supp/eapol_supp_sm.h" 17189251Ssam#include "wpa.h" 18189251Ssam#include "eloop.h" 19189251Ssam#include "preauth.h" 20189251Ssam#include "pmksa_cache.h" 21189251Ssam#include "wpa_i.h" 22189251Ssam#include "wpa_ie.h" 23189251Ssam#include "peerkey.h" 24189251Ssam 25189251Ssam 26189251Ssam/** 27189251Ssam * wpa_eapol_key_send - Send WPA/RSN EAPOL-Key message 28189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 29189251Ssam * @kck: Key Confirmation Key (KCK, part of PTK) 30189251Ssam * @ver: Version field from Key Info 31189251Ssam * @dest: Destination address for the frame 32189251Ssam * @proto: Ethertype (usually ETH_P_EAPOL) 33189251Ssam * @msg: EAPOL-Key message 34189251Ssam * @msg_len: Length of message 35189251Ssam * @key_mic: Pointer to the buffer to which the EAPOL-Key MIC is written 36189251Ssam */ 37189251Ssamvoid wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, 38189251Ssam int ver, const u8 *dest, u16 proto, 39189251Ssam u8 *msg, size_t msg_len, u8 *key_mic) 40189251Ssam{ 41189251Ssam if (is_zero_ether_addr(dest) && is_zero_ether_addr(sm->bssid)) { 42189251Ssam /* 43189251Ssam * Association event was not yet received; try to fetch 44189251Ssam * BSSID from the driver. 45189251Ssam */ 46189251Ssam if (wpa_sm_get_bssid(sm, sm->bssid) < 0) { 47252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 48252726Srpaulo "WPA: Failed to read BSSID for " 49252726Srpaulo "EAPOL-Key destination address"); 50189251Ssam } else { 51189251Ssam dest = sm->bssid; 52252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 53252726Srpaulo "WPA: Use BSSID (" MACSTR 54252726Srpaulo ") as the destination for EAPOL-Key", 55252726Srpaulo MAC2STR(dest)); 56189251Ssam } 57189251Ssam } 58214734Srpaulo if (key_mic && 59214734Srpaulo wpa_eapol_key_mic(kck, ver, msg, msg_len, key_mic)) { 60252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, 61252726Srpaulo "WPA: Failed to generate EAPOL-Key " 62252726Srpaulo "version %d MIC", ver); 63214734Srpaulo goto out; 64214734Srpaulo } 65252726Srpaulo wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", kck, 16); 66252726Srpaulo wpa_hexdump(MSG_DEBUG, "WPA: Derived Key MIC", key_mic, 16); 67189251Ssam wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key", msg, msg_len); 68189251Ssam wpa_sm_ether_send(sm, dest, proto, msg, msg_len); 69189251Ssam eapol_sm_notify_tx_eapol_key(sm->eapol); 70214734Srpauloout: 71189251Ssam os_free(msg); 72189251Ssam} 73189251Ssam 74189251Ssam 75189251Ssam/** 76189251Ssam * wpa_sm_key_request - Send EAPOL-Key Request 77189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 78189251Ssam * @error: Indicate whether this is an Michael MIC error report 79189251Ssam * @pairwise: 1 = error report for pairwise packet, 0 = for group packet 80189251Ssam * 81189251Ssam * Send an EAPOL-Key Request to the current authenticator. This function is 82189251Ssam * used to request rekeying and it is usually called when a local Michael MIC 83189251Ssam * failure is detected. 84189251Ssam */ 85189251Ssamvoid wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) 86189251Ssam{ 87189251Ssam size_t rlen; 88189251Ssam struct wpa_eapol_key *reply; 89189251Ssam int key_info, ver; 90189251Ssam u8 bssid[ETH_ALEN], *rbuf; 91189251Ssam 92189251Ssam if (wpa_key_mgmt_ft(sm->key_mgmt) || wpa_key_mgmt_sha256(sm->key_mgmt)) 93189251Ssam ver = WPA_KEY_INFO_TYPE_AES_128_CMAC; 94252726Srpaulo else if (sm->pairwise_cipher != WPA_CIPHER_TKIP) 95189251Ssam ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; 96189251Ssam else 97189251Ssam ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; 98189251Ssam 99189251Ssam if (wpa_sm_get_bssid(sm, bssid) < 0) { 100252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 101252726Srpaulo "Failed to read BSSID for EAPOL-Key request"); 102189251Ssam return; 103189251Ssam } 104189251Ssam 105189251Ssam rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, 106189251Ssam sizeof(*reply), &rlen, (void *) &reply); 107189251Ssam if (rbuf == NULL) 108189251Ssam return; 109189251Ssam 110189251Ssam reply->type = sm->proto == WPA_PROTO_RSN ? 111189251Ssam EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; 112189251Ssam key_info = WPA_KEY_INFO_REQUEST | ver; 113189251Ssam if (sm->ptk_set) 114189251Ssam key_info |= WPA_KEY_INFO_MIC; 115189251Ssam if (error) 116189251Ssam key_info |= WPA_KEY_INFO_ERROR; 117189251Ssam if (pairwise) 118189251Ssam key_info |= WPA_KEY_INFO_KEY_TYPE; 119189251Ssam WPA_PUT_BE16(reply->key_info, key_info); 120189251Ssam WPA_PUT_BE16(reply->key_length, 0); 121189251Ssam os_memcpy(reply->replay_counter, sm->request_counter, 122189251Ssam WPA_REPLAY_COUNTER_LEN); 123189251Ssam inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); 124189251Ssam 125189251Ssam WPA_PUT_BE16(reply->key_data_length, 0); 126189251Ssam 127252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 128252726Srpaulo "WPA: Sending EAPOL-Key Request (error=%d " 129252726Srpaulo "pairwise=%d ptk_set=%d len=%lu)", 130252726Srpaulo error, pairwise, sm->ptk_set, (unsigned long) rlen); 131189251Ssam wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL, 132189251Ssam rbuf, rlen, key_info & WPA_KEY_INFO_MIC ? 133189251Ssam reply->key_mic : NULL); 134189251Ssam} 135189251Ssam 136189251Ssam 137189251Ssamstatic int wpa_supplicant_get_pmk(struct wpa_sm *sm, 138189251Ssam const unsigned char *src_addr, 139189251Ssam const u8 *pmkid) 140189251Ssam{ 141189251Ssam int abort_cached = 0; 142189251Ssam 143189251Ssam if (pmkid && !sm->cur_pmksa) { 144189251Ssam /* When using drivers that generate RSN IE, wpa_supplicant may 145189251Ssam * not have enough time to get the association information 146189251Ssam * event before receiving this 1/4 message, so try to find a 147189251Ssam * matching PMKSA cache entry here. */ 148252726Srpaulo sm->cur_pmksa = pmksa_cache_get(sm->pmksa, src_addr, pmkid, 149252726Srpaulo NULL); 150189251Ssam if (sm->cur_pmksa) { 151252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 152252726Srpaulo "RSN: found matching PMKID from PMKSA cache"); 153189251Ssam } else { 154252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 155252726Srpaulo "RSN: no matching PMKID found"); 156189251Ssam abort_cached = 1; 157189251Ssam } 158189251Ssam } 159189251Ssam 160189251Ssam if (pmkid && sm->cur_pmksa && 161189251Ssam os_memcmp(pmkid, sm->cur_pmksa->pmkid, PMKID_LEN) == 0) { 162189251Ssam wpa_hexdump(MSG_DEBUG, "RSN: matched PMKID", pmkid, PMKID_LEN); 163189251Ssam wpa_sm_set_pmk_from_pmksa(sm); 164189251Ssam wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from PMKSA cache", 165189251Ssam sm->pmk, sm->pmk_len); 166189251Ssam eapol_sm_notify_cached(sm->eapol); 167189251Ssam#ifdef CONFIG_IEEE80211R 168189251Ssam sm->xxkey_len = 0; 169189251Ssam#endif /* CONFIG_IEEE80211R */ 170189251Ssam } else if (wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) && sm->eapol) { 171189251Ssam int res, pmk_len; 172189251Ssam pmk_len = PMK_LEN; 173189251Ssam res = eapol_sm_get_key(sm->eapol, sm->pmk, PMK_LEN); 174189251Ssam if (res) { 175189251Ssam /* 176189251Ssam * EAP-LEAP is an exception from other EAP methods: it 177189251Ssam * uses only 16-byte PMK. 178189251Ssam */ 179189251Ssam res = eapol_sm_get_key(sm->eapol, sm->pmk, 16); 180189251Ssam pmk_len = 16; 181189251Ssam } else { 182189251Ssam#ifdef CONFIG_IEEE80211R 183189251Ssam u8 buf[2 * PMK_LEN]; 184189251Ssam if (eapol_sm_get_key(sm->eapol, buf, 2 * PMK_LEN) == 0) 185189251Ssam { 186189251Ssam os_memcpy(sm->xxkey, buf + PMK_LEN, PMK_LEN); 187189251Ssam sm->xxkey_len = PMK_LEN; 188189251Ssam os_memset(buf, 0, sizeof(buf)); 189189251Ssam } 190189251Ssam#endif /* CONFIG_IEEE80211R */ 191189251Ssam } 192189251Ssam if (res == 0) { 193252726Srpaulo struct rsn_pmksa_cache_entry *sa = NULL; 194189251Ssam wpa_hexdump_key(MSG_DEBUG, "WPA: PMK from EAPOL state " 195189251Ssam "machines", sm->pmk, pmk_len); 196189251Ssam sm->pmk_len = pmk_len; 197252726Srpaulo if (sm->proto == WPA_PROTO_RSN && 198252726Srpaulo !wpa_key_mgmt_ft(sm->key_mgmt)) { 199252726Srpaulo sa = pmksa_cache_add(sm->pmksa, 200252726Srpaulo sm->pmk, pmk_len, 201252726Srpaulo src_addr, sm->own_addr, 202252726Srpaulo sm->network_ctx, 203252726Srpaulo sm->key_mgmt); 204214734Srpaulo } 205189251Ssam if (!sm->cur_pmksa && pmkid && 206252726Srpaulo pmksa_cache_get(sm->pmksa, src_addr, pmkid, NULL)) 207252726Srpaulo { 208252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 209252726Srpaulo "RSN: the new PMK matches with the " 210252726Srpaulo "PMKID"); 211189251Ssam abort_cached = 0; 212189251Ssam } 213252726Srpaulo 214252726Srpaulo if (!sm->cur_pmksa) 215252726Srpaulo sm->cur_pmksa = sa; 216189251Ssam } else { 217214734Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 218189251Ssam "WPA: Failed to get master session key from " 219252726Srpaulo "EAPOL state machines - key handshake " 220252726Srpaulo "aborted"); 221189251Ssam if (sm->cur_pmksa) { 222252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 223252726Srpaulo "RSN: Cancelled PMKSA caching " 224252726Srpaulo "attempt"); 225189251Ssam sm->cur_pmksa = NULL; 226189251Ssam abort_cached = 1; 227189251Ssam } else if (!abort_cached) { 228189251Ssam return -1; 229189251Ssam } 230189251Ssam } 231189251Ssam } 232189251Ssam 233252726Srpaulo if (abort_cached && wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) && 234252726Srpaulo !wpa_key_mgmt_ft(sm->key_mgmt)) { 235189251Ssam /* Send EAPOL-Start to trigger full EAP authentication. */ 236189251Ssam u8 *buf; 237189251Ssam size_t buflen; 238189251Ssam 239252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 240252726Srpaulo "RSN: no PMKSA entry found - trigger " 241252726Srpaulo "full EAP authentication"); 242189251Ssam buf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START, 243189251Ssam NULL, 0, &buflen, NULL); 244189251Ssam if (buf) { 245189251Ssam wpa_sm_ether_send(sm, sm->bssid, ETH_P_EAPOL, 246189251Ssam buf, buflen); 247189251Ssam os_free(buf); 248214734Srpaulo return -2; 249189251Ssam } 250189251Ssam 251189251Ssam return -1; 252189251Ssam } 253189251Ssam 254189251Ssam return 0; 255189251Ssam} 256189251Ssam 257189251Ssam 258189251Ssam/** 259189251Ssam * wpa_supplicant_send_2_of_4 - Send message 2 of WPA/RSN 4-Way Handshake 260189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 261189251Ssam * @dst: Destination address for the frame 262189251Ssam * @key: Pointer to the EAPOL-Key frame header 263189251Ssam * @ver: Version bits from EAPOL-Key Key Info 264189251Ssam * @nonce: Nonce value for the EAPOL-Key frame 265189251Ssam * @wpa_ie: WPA/RSN IE 266189251Ssam * @wpa_ie_len: Length of the WPA/RSN IE 267189251Ssam * @ptk: PTK to use for keyed hash and encryption 268189251Ssam * Returns: 0 on success, -1 on failure 269189251Ssam */ 270189251Ssamint wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, 271189251Ssam const struct wpa_eapol_key *key, 272189251Ssam int ver, const u8 *nonce, 273189251Ssam const u8 *wpa_ie, size_t wpa_ie_len, 274189251Ssam struct wpa_ptk *ptk) 275189251Ssam{ 276189251Ssam size_t rlen; 277189251Ssam struct wpa_eapol_key *reply; 278189251Ssam u8 *rbuf; 279214734Srpaulo u8 *rsn_ie_buf = NULL; 280189251Ssam 281189251Ssam if (wpa_ie == NULL) { 282252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No wpa_ie set - " 283252726Srpaulo "cannot generate msg 2/4"); 284189251Ssam return -1; 285189251Ssam } 286189251Ssam 287214734Srpaulo#ifdef CONFIG_IEEE80211R 288214734Srpaulo if (wpa_key_mgmt_ft(sm->key_mgmt)) { 289214734Srpaulo int res; 290214734Srpaulo 291214734Srpaulo /* 292214734Srpaulo * Add PMKR1Name into RSN IE (PMKID-List) and add MDIE and 293214734Srpaulo * FTIE from (Re)Association Response. 294214734Srpaulo */ 295214734Srpaulo rsn_ie_buf = os_malloc(wpa_ie_len + 2 + 2 + PMKID_LEN + 296214734Srpaulo sm->assoc_resp_ies_len); 297214734Srpaulo if (rsn_ie_buf == NULL) 298214734Srpaulo return -1; 299214734Srpaulo os_memcpy(rsn_ie_buf, wpa_ie, wpa_ie_len); 300214734Srpaulo res = wpa_insert_pmkid(rsn_ie_buf, wpa_ie_len, 301214734Srpaulo sm->pmk_r1_name); 302214734Srpaulo if (res < 0) { 303214734Srpaulo os_free(rsn_ie_buf); 304214734Srpaulo return -1; 305214734Srpaulo } 306214734Srpaulo wpa_ie_len += res; 307214734Srpaulo 308214734Srpaulo if (sm->assoc_resp_ies) { 309214734Srpaulo os_memcpy(rsn_ie_buf + wpa_ie_len, sm->assoc_resp_ies, 310214734Srpaulo sm->assoc_resp_ies_len); 311214734Srpaulo wpa_ie_len += sm->assoc_resp_ies_len; 312214734Srpaulo } 313214734Srpaulo 314214734Srpaulo wpa_ie = rsn_ie_buf; 315214734Srpaulo } 316214734Srpaulo#endif /* CONFIG_IEEE80211R */ 317214734Srpaulo 318189251Ssam wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len); 319189251Ssam 320189251Ssam rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, 321189251Ssam NULL, sizeof(*reply) + wpa_ie_len, 322189251Ssam &rlen, (void *) &reply); 323214734Srpaulo if (rbuf == NULL) { 324214734Srpaulo os_free(rsn_ie_buf); 325189251Ssam return -1; 326214734Srpaulo } 327189251Ssam 328189251Ssam reply->type = sm->proto == WPA_PROTO_RSN ? 329189251Ssam EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; 330189251Ssam WPA_PUT_BE16(reply->key_info, 331189251Ssam ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC); 332189251Ssam if (sm->proto == WPA_PROTO_RSN) 333189251Ssam WPA_PUT_BE16(reply->key_length, 0); 334189251Ssam else 335189251Ssam os_memcpy(reply->key_length, key->key_length, 2); 336189251Ssam os_memcpy(reply->replay_counter, key->replay_counter, 337189251Ssam WPA_REPLAY_COUNTER_LEN); 338252726Srpaulo wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter", reply->replay_counter, 339252726Srpaulo WPA_REPLAY_COUNTER_LEN); 340189251Ssam 341189251Ssam WPA_PUT_BE16(reply->key_data_length, wpa_ie_len); 342189251Ssam os_memcpy(reply + 1, wpa_ie, wpa_ie_len); 343214734Srpaulo os_free(rsn_ie_buf); 344189251Ssam 345189251Ssam os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN); 346189251Ssam 347252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/4"); 348189251Ssam wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL, 349189251Ssam rbuf, rlen, reply->key_mic); 350189251Ssam 351189251Ssam return 0; 352189251Ssam} 353189251Ssam 354189251Ssam 355189251Ssamstatic int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr, 356189251Ssam const struct wpa_eapol_key *key, 357189251Ssam struct wpa_ptk *ptk) 358189251Ssam{ 359252726Srpaulo size_t ptk_len = sm->pairwise_cipher != WPA_CIPHER_TKIP ? 48 : 64; 360189251Ssam#ifdef CONFIG_IEEE80211R 361189251Ssam if (wpa_key_mgmt_ft(sm->key_mgmt)) 362209158Srpaulo return wpa_derive_ptk_ft(sm, src_addr, key, ptk, ptk_len); 363189251Ssam#endif /* CONFIG_IEEE80211R */ 364189251Ssam 365189251Ssam wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion", 366189251Ssam sm->own_addr, sm->bssid, sm->snonce, key->key_nonce, 367209158Srpaulo (u8 *) ptk, ptk_len, 368189251Ssam wpa_key_mgmt_sha256(sm->key_mgmt)); 369189251Ssam return 0; 370189251Ssam} 371189251Ssam 372189251Ssam 373189251Ssamstatic void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, 374189251Ssam const unsigned char *src_addr, 375189251Ssam const struct wpa_eapol_key *key, 376189251Ssam u16 ver) 377189251Ssam{ 378189251Ssam struct wpa_eapol_ie_parse ie; 379189251Ssam struct wpa_ptk *ptk; 380189251Ssam u8 buf[8]; 381214734Srpaulo int res; 382189251Ssam 383189251Ssam if (wpa_sm_get_network_ctx(sm) == NULL) { 384252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No SSID info " 385252726Srpaulo "found (msg 1 of 4)"); 386189251Ssam return; 387189251Ssam } 388189251Ssam 389189251Ssam wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE); 390252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of 4-Way " 391252726Srpaulo "Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver); 392189251Ssam 393189251Ssam os_memset(&ie, 0, sizeof(ie)); 394189251Ssam 395189251Ssam#ifndef CONFIG_NO_WPA2 396189251Ssam if (sm->proto == WPA_PROTO_RSN) { 397189251Ssam /* RSN: msg 1/4 should contain PMKID for the selected PMK */ 398189251Ssam const u8 *_buf = (const u8 *) (key + 1); 399189251Ssam size_t len = WPA_GET_BE16(key->key_data_length); 400189251Ssam wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", _buf, len); 401252726Srpaulo if (wpa_supplicant_parse_ies(_buf, len, &ie) < 0) 402252726Srpaulo goto failed; 403189251Ssam if (ie.pmkid) { 404189251Ssam wpa_hexdump(MSG_DEBUG, "RSN: PMKID from " 405189251Ssam "Authenticator", ie.pmkid, PMKID_LEN); 406189251Ssam } 407189251Ssam } 408189251Ssam#endif /* CONFIG_NO_WPA2 */ 409189251Ssam 410214734Srpaulo res = wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid); 411214734Srpaulo if (res == -2) { 412252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: Do not reply to " 413252726Srpaulo "msg 1/4 - requesting full EAP authentication"); 414214734Srpaulo return; 415214734Srpaulo } 416214734Srpaulo if (res) 417209158Srpaulo goto failed; 418189251Ssam 419189251Ssam if (sm->renew_snonce) { 420252726Srpaulo if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) { 421214734Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 422189251Ssam "WPA: Failed to get random data for SNonce"); 423209158Srpaulo goto failed; 424189251Ssam } 425189251Ssam sm->renew_snonce = 0; 426189251Ssam wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce", 427189251Ssam sm->snonce, WPA_NONCE_LEN); 428189251Ssam } 429189251Ssam 430189251Ssam /* Calculate PTK which will be stored as a temporary PTK until it has 431189251Ssam * been verified when processing message 3/4. */ 432189251Ssam ptk = &sm->tptk; 433189251Ssam wpa_derive_ptk(sm, src_addr, key, ptk); 434189251Ssam /* Supplicant: swap tx/rx Mic keys */ 435189251Ssam os_memcpy(buf, ptk->u.auth.tx_mic_key, 8); 436189251Ssam os_memcpy(ptk->u.auth.tx_mic_key, ptk->u.auth.rx_mic_key, 8); 437189251Ssam os_memcpy(ptk->u.auth.rx_mic_key, buf, 8); 438189251Ssam sm->tptk_set = 1; 439189251Ssam 440189251Ssam if (wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, sm->snonce, 441189251Ssam sm->assoc_wpa_ie, sm->assoc_wpa_ie_len, 442189251Ssam ptk)) 443209158Srpaulo goto failed; 444189251Ssam 445189251Ssam os_memcpy(sm->anonce, key->key_nonce, WPA_NONCE_LEN); 446209158Srpaulo return; 447209158Srpaulo 448209158Srpaulofailed: 449209158Srpaulo wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); 450189251Ssam} 451189251Ssam 452189251Ssam 453189251Ssamstatic void wpa_sm_start_preauth(void *eloop_ctx, void *timeout_ctx) 454189251Ssam{ 455189251Ssam struct wpa_sm *sm = eloop_ctx; 456189251Ssam rsn_preauth_candidate_process(sm); 457189251Ssam} 458189251Ssam 459189251Ssam 460189251Ssamstatic void wpa_supplicant_key_neg_complete(struct wpa_sm *sm, 461189251Ssam const u8 *addr, int secure) 462189251Ssam{ 463214734Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 464214734Srpaulo "WPA: Key negotiation completed with " 465189251Ssam MACSTR " [PTK=%s GTK=%s]", MAC2STR(addr), 466189251Ssam wpa_cipher_txt(sm->pairwise_cipher), 467189251Ssam wpa_cipher_txt(sm->group_cipher)); 468189251Ssam wpa_sm_cancel_auth_timeout(sm); 469189251Ssam wpa_sm_set_state(sm, WPA_COMPLETED); 470189251Ssam 471189251Ssam if (secure) { 472189251Ssam wpa_sm_mlme_setprotection( 473189251Ssam sm, addr, MLME_SETPROTECTION_PROTECT_TYPE_RX_TX, 474189251Ssam MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); 475189251Ssam eapol_sm_notify_portValid(sm->eapol, TRUE); 476189251Ssam if (wpa_key_mgmt_wpa_psk(sm->key_mgmt)) 477189251Ssam eapol_sm_notify_eap_success(sm->eapol, TRUE); 478189251Ssam /* 479189251Ssam * Start preauthentication after a short wait to avoid a 480189251Ssam * possible race condition between the data receive and key 481189251Ssam * configuration after the 4-Way Handshake. This increases the 482252726Srpaulo * likelihood of the first preauth EAPOL-Start frame getting to 483189251Ssam * the target AP. 484189251Ssam */ 485189251Ssam eloop_register_timeout(1, 0, wpa_sm_start_preauth, sm, NULL); 486189251Ssam } 487189251Ssam 488189251Ssam if (sm->cur_pmksa && sm->cur_pmksa->opportunistic) { 489252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 490252726Srpaulo "RSN: Authenticator accepted " 491252726Srpaulo "opportunistic PMKSA entry - marking it valid"); 492189251Ssam sm->cur_pmksa->opportunistic = 0; 493189251Ssam } 494189251Ssam 495189251Ssam#ifdef CONFIG_IEEE80211R 496189251Ssam if (wpa_key_mgmt_ft(sm->key_mgmt)) { 497189251Ssam /* Prepare for the next transition */ 498214734Srpaulo wpa_ft_prepare_auth_request(sm, NULL); 499189251Ssam } 500189251Ssam#endif /* CONFIG_IEEE80211R */ 501189251Ssam} 502189251Ssam 503189251Ssam 504189251Ssamstatic void wpa_sm_rekey_ptk(void *eloop_ctx, void *timeout_ctx) 505189251Ssam{ 506189251Ssam struct wpa_sm *sm = eloop_ctx; 507252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Request PTK rekeying"); 508189251Ssam wpa_sm_key_request(sm, 0, 1); 509189251Ssam} 510189251Ssam 511189251Ssam 512189251Ssamstatic int wpa_supplicant_install_ptk(struct wpa_sm *sm, 513189251Ssam const struct wpa_eapol_key *key) 514189251Ssam{ 515189251Ssam int keylen, rsclen; 516214734Srpaulo enum wpa_alg alg; 517189251Ssam const u8 *key_rsc; 518189251Ssam u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 519189251Ssam 520252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 521252726Srpaulo "WPA: Installing PTK to the driver"); 522189251Ssam 523252726Srpaulo if (sm->pairwise_cipher == WPA_CIPHER_NONE) { 524252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Pairwise Cipher " 525252726Srpaulo "Suite: NONE - do not use pairwise keys"); 526189251Ssam return 0; 527252726Srpaulo } 528252726Srpaulo 529252726Srpaulo if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) { 530252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 531252726Srpaulo "WPA: Unsupported pairwise cipher %d", 532252726Srpaulo sm->pairwise_cipher); 533189251Ssam return -1; 534189251Ssam } 535189251Ssam 536252726Srpaulo alg = wpa_cipher_to_alg(sm->pairwise_cipher); 537252726Srpaulo keylen = wpa_cipher_key_len(sm->pairwise_cipher); 538252726Srpaulo rsclen = wpa_cipher_rsc_len(sm->pairwise_cipher); 539252726Srpaulo 540189251Ssam if (sm->proto == WPA_PROTO_RSN) { 541189251Ssam key_rsc = null_rsc; 542189251Ssam } else { 543189251Ssam key_rsc = key->key_rsc; 544189251Ssam wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, rsclen); 545189251Ssam } 546189251Ssam 547189251Ssam if (wpa_sm_set_key(sm, alg, sm->bssid, 0, 1, key_rsc, rsclen, 548189251Ssam (u8 *) sm->ptk.tk1, keylen) < 0) { 549252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 550252726Srpaulo "WPA: Failed to set PTK to the " 551252726Srpaulo "driver (alg=%d keylen=%d bssid=" MACSTR ")", 552252726Srpaulo alg, keylen, MAC2STR(sm->bssid)); 553189251Ssam return -1; 554189251Ssam } 555189251Ssam 556189251Ssam if (sm->wpa_ptk_rekey) { 557189251Ssam eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL); 558189251Ssam eloop_register_timeout(sm->wpa_ptk_rekey, 0, wpa_sm_rekey_ptk, 559189251Ssam sm, NULL); 560189251Ssam } 561189251Ssam 562189251Ssam return 0; 563189251Ssam} 564189251Ssam 565189251Ssam 566252726Srpaulostatic int wpa_supplicant_check_group_cipher(struct wpa_sm *sm, 567252726Srpaulo int group_cipher, 568189251Ssam int keylen, int maxkeylen, 569214734Srpaulo int *key_rsc_len, 570214734Srpaulo enum wpa_alg *alg) 571189251Ssam{ 572252726Srpaulo int klen; 573189251Ssam 574252726Srpaulo *alg = wpa_cipher_to_alg(group_cipher); 575252726Srpaulo if (*alg == WPA_ALG_NONE) { 576252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 577252726Srpaulo "WPA: Unsupported Group Cipher %d", 578252726Srpaulo group_cipher); 579189251Ssam return -1; 580189251Ssam } 581252726Srpaulo *key_rsc_len = wpa_cipher_rsc_len(group_cipher); 582189251Ssam 583252726Srpaulo klen = wpa_cipher_key_len(group_cipher); 584252726Srpaulo if (keylen != klen || maxkeylen < klen) { 585252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 586252726Srpaulo "WPA: Unsupported %s Group Cipher key length %d (%d)", 587252726Srpaulo wpa_cipher_txt(group_cipher), keylen, maxkeylen); 588252726Srpaulo return -1; 589189251Ssam } 590252726Srpaulo return 0; 591189251Ssam} 592189251Ssam 593189251Ssam 594189251Ssamstruct wpa_gtk_data { 595214734Srpaulo enum wpa_alg alg; 596189251Ssam int tx, key_rsc_len, keyidx; 597189251Ssam u8 gtk[32]; 598189251Ssam int gtk_len; 599189251Ssam}; 600189251Ssam 601189251Ssam 602189251Ssamstatic int wpa_supplicant_install_gtk(struct wpa_sm *sm, 603189251Ssam const struct wpa_gtk_data *gd, 604189251Ssam const u8 *key_rsc) 605189251Ssam{ 606189251Ssam const u8 *_gtk = gd->gtk; 607189251Ssam u8 gtk_buf[32]; 608189251Ssam 609189251Ssam wpa_hexdump_key(MSG_DEBUG, "WPA: Group Key", gd->gtk, gd->gtk_len); 610252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 611252726Srpaulo "WPA: Installing GTK to the driver (keyidx=%d tx=%d len=%d)", 612252726Srpaulo gd->keyidx, gd->tx, gd->gtk_len); 613189251Ssam wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, gd->key_rsc_len); 614189251Ssam if (sm->group_cipher == WPA_CIPHER_TKIP) { 615189251Ssam /* Swap Tx/Rx keys for Michael MIC */ 616189251Ssam os_memcpy(gtk_buf, gd->gtk, 16); 617189251Ssam os_memcpy(gtk_buf + 16, gd->gtk + 24, 8); 618189251Ssam os_memcpy(gtk_buf + 24, gd->gtk + 16, 8); 619189251Ssam _gtk = gtk_buf; 620189251Ssam } 621189251Ssam if (sm->pairwise_cipher == WPA_CIPHER_NONE) { 622252726Srpaulo if (wpa_sm_set_key(sm, gd->alg, NULL, 623189251Ssam gd->keyidx, 1, key_rsc, gd->key_rsc_len, 624189251Ssam _gtk, gd->gtk_len) < 0) { 625252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 626252726Srpaulo "WPA: Failed to set GTK to the driver " 627252726Srpaulo "(Group only)"); 628189251Ssam return -1; 629189251Ssam } 630252726Srpaulo } else if (wpa_sm_set_key(sm, gd->alg, broadcast_ether_addr, 631189251Ssam gd->keyidx, gd->tx, key_rsc, gd->key_rsc_len, 632189251Ssam _gtk, gd->gtk_len) < 0) { 633252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 634252726Srpaulo "WPA: Failed to set GTK to " 635252726Srpaulo "the driver (alg=%d keylen=%d keyidx=%d)", 636252726Srpaulo gd->alg, gd->gtk_len, gd->keyidx); 637189251Ssam return -1; 638189251Ssam } 639189251Ssam 640189251Ssam return 0; 641189251Ssam} 642189251Ssam 643189251Ssam 644189251Ssamstatic int wpa_supplicant_gtk_tx_bit_workaround(const struct wpa_sm *sm, 645189251Ssam int tx) 646189251Ssam{ 647189251Ssam if (tx && sm->pairwise_cipher != WPA_CIPHER_NONE) { 648189251Ssam /* Ignore Tx bit for GTK if a pairwise key is used. One AP 649189251Ssam * seemed to set this bit (incorrectly, since Tx is only when 650189251Ssam * doing Group Key only APs) and without this workaround, the 651189251Ssam * data connection does not work because wpa_supplicant 652189251Ssam * configured non-zero keyidx to be used for unicast. */ 653252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 654252726Srpaulo "WPA: Tx bit set for GTK, but pairwise " 655252726Srpaulo "keys are used - ignore Tx bit"); 656189251Ssam return 0; 657189251Ssam } 658189251Ssam return tx; 659189251Ssam} 660189251Ssam 661189251Ssam 662189251Ssamstatic int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm, 663189251Ssam const struct wpa_eapol_key *key, 664189251Ssam const u8 *gtk, size_t gtk_len, 665189251Ssam int key_info) 666189251Ssam{ 667189251Ssam#ifndef CONFIG_NO_WPA2 668189251Ssam struct wpa_gtk_data gd; 669189251Ssam 670189251Ssam /* 671189251Ssam * IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames - Figure 43x 672189251Ssam * GTK KDE format: 673189251Ssam * KeyID[bits 0-1], Tx [bit 2], Reserved [bits 3-7] 674189251Ssam * Reserved [bits 0-7] 675189251Ssam * GTK 676189251Ssam */ 677189251Ssam 678189251Ssam os_memset(&gd, 0, sizeof(gd)); 679189251Ssam wpa_hexdump_key(MSG_DEBUG, "RSN: received GTK in pairwise handshake", 680189251Ssam gtk, gtk_len); 681189251Ssam 682189251Ssam if (gtk_len < 2 || gtk_len - 2 > sizeof(gd.gtk)) 683189251Ssam return -1; 684189251Ssam 685189251Ssam gd.keyidx = gtk[0] & 0x3; 686189251Ssam gd.tx = wpa_supplicant_gtk_tx_bit_workaround(sm, 687189251Ssam !!(gtk[0] & BIT(2))); 688189251Ssam gtk += 2; 689189251Ssam gtk_len -= 2; 690189251Ssam 691189251Ssam os_memcpy(gd.gtk, gtk, gtk_len); 692189251Ssam gd.gtk_len = gtk_len; 693189251Ssam 694252726Srpaulo if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher, 695189251Ssam gtk_len, gtk_len, 696189251Ssam &gd.key_rsc_len, &gd.alg) || 697189251Ssam wpa_supplicant_install_gtk(sm, &gd, key->key_rsc)) { 698252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 699252726Srpaulo "RSN: Failed to install GTK"); 700189251Ssam return -1; 701189251Ssam } 702189251Ssam 703189251Ssam wpa_supplicant_key_neg_complete(sm, sm->bssid, 704189251Ssam key_info & WPA_KEY_INFO_SECURE); 705189251Ssam return 0; 706189251Ssam#else /* CONFIG_NO_WPA2 */ 707189251Ssam return -1; 708189251Ssam#endif /* CONFIG_NO_WPA2 */ 709189251Ssam} 710189251Ssam 711189251Ssam 712189251Ssamstatic int ieee80211w_set_keys(struct wpa_sm *sm, 713189251Ssam struct wpa_eapol_ie_parse *ie) 714189251Ssam{ 715189251Ssam#ifdef CONFIG_IEEE80211W 716189251Ssam if (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) 717189251Ssam return 0; 718189251Ssam 719189251Ssam if (ie->igtk) { 720189251Ssam const struct wpa_igtk_kde *igtk; 721189251Ssam u16 keyidx; 722189251Ssam if (ie->igtk_len != sizeof(*igtk)) 723189251Ssam return -1; 724189251Ssam igtk = (const struct wpa_igtk_kde *) ie->igtk; 725189251Ssam keyidx = WPA_GET_LE16(igtk->keyid); 726252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: IGTK keyid %d " 727252726Srpaulo "pn %02x%02x%02x%02x%02x%02x", 728252726Srpaulo keyidx, MAC2STR(igtk->pn)); 729189251Ssam wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK", 730189251Ssam igtk->igtk, WPA_IGTK_LEN); 731189251Ssam if (keyidx > 4095) { 732252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 733252726Srpaulo "WPA: Invalid IGTK KeyID %d", keyidx); 734189251Ssam return -1; 735189251Ssam } 736252726Srpaulo if (wpa_sm_set_key(sm, WPA_ALG_IGTK, broadcast_ether_addr, 737189251Ssam keyidx, 0, igtk->pn, sizeof(igtk->pn), 738189251Ssam igtk->igtk, WPA_IGTK_LEN) < 0) { 739252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 740252726Srpaulo "WPA: Failed to configure IGTK to the driver"); 741189251Ssam return -1; 742189251Ssam } 743189251Ssam } 744189251Ssam 745189251Ssam return 0; 746189251Ssam#else /* CONFIG_IEEE80211W */ 747189251Ssam return 0; 748189251Ssam#endif /* CONFIG_IEEE80211W */ 749189251Ssam} 750189251Ssam 751189251Ssam 752189251Ssamstatic void wpa_report_ie_mismatch(struct wpa_sm *sm, 753189251Ssam const char *reason, const u8 *src_addr, 754189251Ssam const u8 *wpa_ie, size_t wpa_ie_len, 755189251Ssam const u8 *rsn_ie, size_t rsn_ie_len) 756189251Ssam{ 757214734Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: %s (src=" MACSTR ")", 758189251Ssam reason, MAC2STR(src_addr)); 759189251Ssam 760189251Ssam if (sm->ap_wpa_ie) { 761189251Ssam wpa_hexdump(MSG_INFO, "WPA: WPA IE in Beacon/ProbeResp", 762189251Ssam sm->ap_wpa_ie, sm->ap_wpa_ie_len); 763189251Ssam } 764189251Ssam if (wpa_ie) { 765189251Ssam if (!sm->ap_wpa_ie) { 766252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 767252726Srpaulo "WPA: No WPA IE in Beacon/ProbeResp"); 768189251Ssam } 769189251Ssam wpa_hexdump(MSG_INFO, "WPA: WPA IE in 3/4 msg", 770189251Ssam wpa_ie, wpa_ie_len); 771189251Ssam } 772189251Ssam 773189251Ssam if (sm->ap_rsn_ie) { 774189251Ssam wpa_hexdump(MSG_INFO, "WPA: RSN IE in Beacon/ProbeResp", 775189251Ssam sm->ap_rsn_ie, sm->ap_rsn_ie_len); 776189251Ssam } 777189251Ssam if (rsn_ie) { 778189251Ssam if (!sm->ap_rsn_ie) { 779252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 780252726Srpaulo "WPA: No RSN IE in Beacon/ProbeResp"); 781189251Ssam } 782189251Ssam wpa_hexdump(MSG_INFO, "WPA: RSN IE in 3/4 msg", 783189251Ssam rsn_ie, rsn_ie_len); 784189251Ssam } 785189251Ssam 786252726Srpaulo wpa_sm_deauthenticate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS); 787189251Ssam} 788189251Ssam 789189251Ssam 790214734Srpaulo#ifdef CONFIG_IEEE80211R 791214734Srpaulo 792214734Srpaulostatic int ft_validate_mdie(struct wpa_sm *sm, 793214734Srpaulo const unsigned char *src_addr, 794214734Srpaulo struct wpa_eapol_ie_parse *ie, 795214734Srpaulo const u8 *assoc_resp_mdie) 796214734Srpaulo{ 797214734Srpaulo struct rsn_mdie *mdie; 798214734Srpaulo 799214734Srpaulo mdie = (struct rsn_mdie *) (ie->mdie + 2); 800214734Srpaulo if (ie->mdie == NULL || ie->mdie_len < 2 + sizeof(*mdie) || 801214734Srpaulo os_memcmp(mdie->mobility_domain, sm->mobility_domain, 802214734Srpaulo MOBILITY_DOMAIN_ID_LEN) != 0) { 803252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: MDIE in msg 3/4 did " 804252726Srpaulo "not match with the current mobility domain"); 805214734Srpaulo return -1; 806214734Srpaulo } 807214734Srpaulo 808214734Srpaulo if (assoc_resp_mdie && 809214734Srpaulo (assoc_resp_mdie[1] != ie->mdie[1] || 810214734Srpaulo os_memcmp(assoc_resp_mdie, ie->mdie, 2 + ie->mdie[1]) != 0)) { 811252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: MDIE mismatch"); 812214734Srpaulo wpa_hexdump(MSG_DEBUG, "FT: MDIE in EAPOL-Key msg 3/4", 813214734Srpaulo ie->mdie, 2 + ie->mdie[1]); 814214734Srpaulo wpa_hexdump(MSG_DEBUG, "FT: MDIE in (Re)Association Response", 815214734Srpaulo assoc_resp_mdie, 2 + assoc_resp_mdie[1]); 816214734Srpaulo return -1; 817214734Srpaulo } 818214734Srpaulo 819214734Srpaulo return 0; 820214734Srpaulo} 821214734Srpaulo 822214734Srpaulo 823214734Srpaulostatic int ft_validate_ftie(struct wpa_sm *sm, 824214734Srpaulo const unsigned char *src_addr, 825214734Srpaulo struct wpa_eapol_ie_parse *ie, 826214734Srpaulo const u8 *assoc_resp_ftie) 827214734Srpaulo{ 828214734Srpaulo if (ie->ftie == NULL) { 829252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 830252726Srpaulo "FT: No FTIE in EAPOL-Key msg 3/4"); 831214734Srpaulo return -1; 832214734Srpaulo } 833214734Srpaulo 834214734Srpaulo if (assoc_resp_ftie == NULL) 835214734Srpaulo return 0; 836214734Srpaulo 837214734Srpaulo if (assoc_resp_ftie[1] != ie->ftie[1] || 838214734Srpaulo os_memcmp(assoc_resp_ftie, ie->ftie, 2 + ie->ftie[1]) != 0) { 839252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: FTIE mismatch"); 840214734Srpaulo wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 3/4", 841214734Srpaulo ie->ftie, 2 + ie->ftie[1]); 842214734Srpaulo wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)Association Response", 843214734Srpaulo assoc_resp_ftie, 2 + assoc_resp_ftie[1]); 844214734Srpaulo return -1; 845214734Srpaulo } 846214734Srpaulo 847214734Srpaulo return 0; 848214734Srpaulo} 849214734Srpaulo 850214734Srpaulo 851214734Srpaulostatic int ft_validate_rsnie(struct wpa_sm *sm, 852214734Srpaulo const unsigned char *src_addr, 853214734Srpaulo struct wpa_eapol_ie_parse *ie) 854214734Srpaulo{ 855214734Srpaulo struct wpa_ie_data rsn; 856214734Srpaulo 857214734Srpaulo if (!ie->rsn_ie) 858214734Srpaulo return 0; 859214734Srpaulo 860214734Srpaulo /* 861214734Srpaulo * Verify that PMKR1Name from EAPOL-Key message 3/4 862214734Srpaulo * matches with the value we derived. 863214734Srpaulo */ 864214734Srpaulo if (wpa_parse_wpa_ie_rsn(ie->rsn_ie, ie->rsn_ie_len, &rsn) < 0 || 865214734Srpaulo rsn.num_pmkid != 1 || rsn.pmkid == NULL) { 866252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: No PMKR1Name in " 867252726Srpaulo "FT 4-way handshake message 3/4"); 868214734Srpaulo return -1; 869214734Srpaulo } 870214734Srpaulo 871214734Srpaulo if (os_memcmp(rsn.pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0) { 872252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 873252726Srpaulo "FT: PMKR1Name mismatch in " 874252726Srpaulo "FT 4-way handshake message 3/4"); 875214734Srpaulo wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Authenticator", 876214734Srpaulo rsn.pmkid, WPA_PMK_NAME_LEN); 877214734Srpaulo wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name", 878214734Srpaulo sm->pmk_r1_name, WPA_PMK_NAME_LEN); 879214734Srpaulo return -1; 880214734Srpaulo } 881214734Srpaulo 882214734Srpaulo return 0; 883214734Srpaulo} 884214734Srpaulo 885214734Srpaulo 886214734Srpaulostatic int wpa_supplicant_validate_ie_ft(struct wpa_sm *sm, 887214734Srpaulo const unsigned char *src_addr, 888214734Srpaulo struct wpa_eapol_ie_parse *ie) 889214734Srpaulo{ 890214734Srpaulo const u8 *pos, *end, *mdie = NULL, *ftie = NULL; 891214734Srpaulo 892214734Srpaulo if (sm->assoc_resp_ies) { 893214734Srpaulo pos = sm->assoc_resp_ies; 894214734Srpaulo end = pos + sm->assoc_resp_ies_len; 895214734Srpaulo while (pos + 2 < end) { 896214734Srpaulo if (pos + 2 + pos[1] > end) 897214734Srpaulo break; 898214734Srpaulo switch (*pos) { 899214734Srpaulo case WLAN_EID_MOBILITY_DOMAIN: 900214734Srpaulo mdie = pos; 901214734Srpaulo break; 902214734Srpaulo case WLAN_EID_FAST_BSS_TRANSITION: 903214734Srpaulo ftie = pos; 904214734Srpaulo break; 905214734Srpaulo } 906214734Srpaulo pos += 2 + pos[1]; 907214734Srpaulo } 908214734Srpaulo } 909214734Srpaulo 910214734Srpaulo if (ft_validate_mdie(sm, src_addr, ie, mdie) < 0 || 911214734Srpaulo ft_validate_ftie(sm, src_addr, ie, ftie) < 0 || 912214734Srpaulo ft_validate_rsnie(sm, src_addr, ie) < 0) 913214734Srpaulo return -1; 914214734Srpaulo 915214734Srpaulo return 0; 916214734Srpaulo} 917214734Srpaulo 918214734Srpaulo#endif /* CONFIG_IEEE80211R */ 919214734Srpaulo 920214734Srpaulo 921189251Ssamstatic int wpa_supplicant_validate_ie(struct wpa_sm *sm, 922189251Ssam const unsigned char *src_addr, 923189251Ssam struct wpa_eapol_ie_parse *ie) 924189251Ssam{ 925189251Ssam if (sm->ap_wpa_ie == NULL && sm->ap_rsn_ie == NULL) { 926252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 927252726Srpaulo "WPA: No WPA/RSN IE for this AP known. " 928252726Srpaulo "Trying to get from scan results"); 929189251Ssam if (wpa_sm_get_beacon_ie(sm) < 0) { 930252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 931252726Srpaulo "WPA: Could not find AP from " 932252726Srpaulo "the scan results"); 933189251Ssam } else { 934252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, 935252726Srpaulo "WPA: Found the current AP from " 936252726Srpaulo "updated scan results"); 937189251Ssam } 938189251Ssam } 939189251Ssam 940189251Ssam if (ie->wpa_ie == NULL && ie->rsn_ie == NULL && 941189251Ssam (sm->ap_wpa_ie || sm->ap_rsn_ie)) { 942189251Ssam wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match " 943189251Ssam "with IE in Beacon/ProbeResp (no IE?)", 944189251Ssam src_addr, ie->wpa_ie, ie->wpa_ie_len, 945189251Ssam ie->rsn_ie, ie->rsn_ie_len); 946189251Ssam return -1; 947189251Ssam } 948189251Ssam 949189251Ssam if ((ie->wpa_ie && sm->ap_wpa_ie && 950189251Ssam (ie->wpa_ie_len != sm->ap_wpa_ie_len || 951189251Ssam os_memcmp(ie->wpa_ie, sm->ap_wpa_ie, ie->wpa_ie_len) != 0)) || 952189251Ssam (ie->rsn_ie && sm->ap_rsn_ie && 953214734Srpaulo wpa_compare_rsn_ie(wpa_key_mgmt_ft(sm->key_mgmt), 954214734Srpaulo sm->ap_rsn_ie, sm->ap_rsn_ie_len, 955214734Srpaulo ie->rsn_ie, ie->rsn_ie_len))) { 956189251Ssam wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match " 957189251Ssam "with IE in Beacon/ProbeResp", 958189251Ssam src_addr, ie->wpa_ie, ie->wpa_ie_len, 959189251Ssam ie->rsn_ie, ie->rsn_ie_len); 960189251Ssam return -1; 961189251Ssam } 962189251Ssam 963189251Ssam if (sm->proto == WPA_PROTO_WPA && 964189251Ssam ie->rsn_ie && sm->ap_rsn_ie == NULL && sm->rsn_enabled) { 965189251Ssam wpa_report_ie_mismatch(sm, "Possible downgrade attack " 966189251Ssam "detected - RSN was enabled and RSN IE " 967189251Ssam "was in msg 3/4, but not in " 968189251Ssam "Beacon/ProbeResp", 969189251Ssam src_addr, ie->wpa_ie, ie->wpa_ie_len, 970189251Ssam ie->rsn_ie, ie->rsn_ie_len); 971189251Ssam return -1; 972189251Ssam } 973189251Ssam 974189251Ssam#ifdef CONFIG_IEEE80211R 975214734Srpaulo if (wpa_key_mgmt_ft(sm->key_mgmt) && 976214734Srpaulo wpa_supplicant_validate_ie_ft(sm, src_addr, ie) < 0) 977214734Srpaulo return -1; 978189251Ssam#endif /* CONFIG_IEEE80211R */ 979189251Ssam 980189251Ssam return 0; 981189251Ssam} 982189251Ssam 983189251Ssam 984189251Ssam/** 985189251Ssam * wpa_supplicant_send_4_of_4 - Send message 4 of WPA/RSN 4-Way Handshake 986189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 987189251Ssam * @dst: Destination address for the frame 988189251Ssam * @key: Pointer to the EAPOL-Key frame header 989189251Ssam * @ver: Version bits from EAPOL-Key Key Info 990189251Ssam * @key_info: Key Info 991189251Ssam * @kde: KDEs to include the EAPOL-Key frame 992189251Ssam * @kde_len: Length of KDEs 993189251Ssam * @ptk: PTK to use for keyed hash and encryption 994189251Ssam * Returns: 0 on success, -1 on failure 995189251Ssam */ 996189251Ssamint wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst, 997189251Ssam const struct wpa_eapol_key *key, 998189251Ssam u16 ver, u16 key_info, 999189251Ssam const u8 *kde, size_t kde_len, 1000189251Ssam struct wpa_ptk *ptk) 1001189251Ssam{ 1002189251Ssam size_t rlen; 1003189251Ssam struct wpa_eapol_key *reply; 1004189251Ssam u8 *rbuf; 1005189251Ssam 1006189251Ssam if (kde) 1007189251Ssam wpa_hexdump(MSG_DEBUG, "WPA: KDE for msg 4/4", kde, kde_len); 1008189251Ssam 1009189251Ssam rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, 1010189251Ssam sizeof(*reply) + kde_len, 1011189251Ssam &rlen, (void *) &reply); 1012189251Ssam if (rbuf == NULL) 1013189251Ssam return -1; 1014189251Ssam 1015189251Ssam reply->type = sm->proto == WPA_PROTO_RSN ? 1016189251Ssam EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; 1017189251Ssam key_info &= WPA_KEY_INFO_SECURE; 1018189251Ssam key_info |= ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC; 1019189251Ssam WPA_PUT_BE16(reply->key_info, key_info); 1020189251Ssam if (sm->proto == WPA_PROTO_RSN) 1021189251Ssam WPA_PUT_BE16(reply->key_length, 0); 1022189251Ssam else 1023189251Ssam os_memcpy(reply->key_length, key->key_length, 2); 1024189251Ssam os_memcpy(reply->replay_counter, key->replay_counter, 1025189251Ssam WPA_REPLAY_COUNTER_LEN); 1026189251Ssam 1027189251Ssam WPA_PUT_BE16(reply->key_data_length, kde_len); 1028189251Ssam if (kde) 1029189251Ssam os_memcpy(reply + 1, kde, kde_len); 1030189251Ssam 1031252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 4/4"); 1032189251Ssam wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL, 1033189251Ssam rbuf, rlen, reply->key_mic); 1034189251Ssam 1035189251Ssam return 0; 1036189251Ssam} 1037189251Ssam 1038189251Ssam 1039189251Ssamstatic void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, 1040189251Ssam const struct wpa_eapol_key *key, 1041189251Ssam u16 ver) 1042189251Ssam{ 1043189251Ssam u16 key_info, keylen, len; 1044189251Ssam const u8 *pos; 1045189251Ssam struct wpa_eapol_ie_parse ie; 1046189251Ssam 1047189251Ssam wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE); 1048252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 3 of 4-Way " 1049252726Srpaulo "Handshake from " MACSTR " (ver=%d)", MAC2STR(sm->bssid), ver); 1050189251Ssam 1051189251Ssam key_info = WPA_GET_BE16(key->key_info); 1052189251Ssam 1053189251Ssam pos = (const u8 *) (key + 1); 1054189251Ssam len = WPA_GET_BE16(key->key_data_length); 1055189251Ssam wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", pos, len); 1056252726Srpaulo if (wpa_supplicant_parse_ies(pos, len, &ie) < 0) 1057252726Srpaulo goto failed; 1058189251Ssam if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { 1059252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1060252726Srpaulo "WPA: GTK IE in unencrypted key data"); 1061209158Srpaulo goto failed; 1062189251Ssam } 1063189251Ssam#ifdef CONFIG_IEEE80211W 1064189251Ssam if (ie.igtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { 1065252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1066252726Srpaulo "WPA: IGTK KDE in unencrypted key data"); 1067209158Srpaulo goto failed; 1068189251Ssam } 1069189251Ssam 1070189251Ssam if (ie.igtk && ie.igtk_len != sizeof(struct wpa_igtk_kde)) { 1071252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1072252726Srpaulo "WPA: Invalid IGTK KDE length %lu", 1073252726Srpaulo (unsigned long) ie.igtk_len); 1074209158Srpaulo goto failed; 1075189251Ssam } 1076189251Ssam#endif /* CONFIG_IEEE80211W */ 1077189251Ssam 1078189251Ssam if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0) 1079209158Srpaulo goto failed; 1080189251Ssam 1081189251Ssam if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) { 1082252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1083252726Srpaulo "WPA: ANonce from message 1 of 4-Way Handshake " 1084252726Srpaulo "differs from 3 of 4-Way Handshake - drop packet (src=" 1085252726Srpaulo MACSTR ")", MAC2STR(sm->bssid)); 1086209158Srpaulo goto failed; 1087189251Ssam } 1088189251Ssam 1089189251Ssam keylen = WPA_GET_BE16(key->key_length); 1090252726Srpaulo if (keylen != wpa_cipher_key_len(sm->pairwise_cipher)) { 1091252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1092252726Srpaulo "WPA: Invalid %s key length %d (src=" MACSTR 1093252726Srpaulo ")", wpa_cipher_txt(sm->pairwise_cipher), keylen, 1094252726Srpaulo MAC2STR(sm->bssid)); 1095252726Srpaulo goto failed; 1096189251Ssam } 1097189251Ssam 1098189251Ssam if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info, 1099209158Srpaulo NULL, 0, &sm->ptk)) { 1100209158Srpaulo goto failed; 1101209158Srpaulo } 1102189251Ssam 1103189251Ssam /* SNonce was successfully used in msg 3/4, so mark it to be renewed 1104189251Ssam * for the next 4-Way Handshake. If msg 3 is received again, the old 1105189251Ssam * SNonce will still be used to avoid changing PTK. */ 1106189251Ssam sm->renew_snonce = 1; 1107189251Ssam 1108189251Ssam if (key_info & WPA_KEY_INFO_INSTALL) { 1109209158Srpaulo if (wpa_supplicant_install_ptk(sm, key)) 1110209158Srpaulo goto failed; 1111189251Ssam } 1112189251Ssam 1113189251Ssam if (key_info & WPA_KEY_INFO_SECURE) { 1114189251Ssam wpa_sm_mlme_setprotection( 1115189251Ssam sm, sm->bssid, MLME_SETPROTECTION_PROTECT_TYPE_RX, 1116189251Ssam MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); 1117189251Ssam eapol_sm_notify_portValid(sm->eapol, TRUE); 1118189251Ssam } 1119189251Ssam wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE); 1120189251Ssam 1121189251Ssam if (ie.gtk && 1122189251Ssam wpa_supplicant_pairwise_gtk(sm, key, 1123189251Ssam ie.gtk, ie.gtk_len, key_info) < 0) { 1124252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 1125252726Srpaulo "RSN: Failed to configure GTK"); 1126209158Srpaulo goto failed; 1127189251Ssam } 1128189251Ssam 1129209158Srpaulo if (ieee80211w_set_keys(sm, &ie) < 0) { 1130252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 1131252726Srpaulo "RSN: Failed to configure IGTK"); 1132209158Srpaulo goto failed; 1133209158Srpaulo } 1134209158Srpaulo 1135252726Srpaulo wpa_sm_set_rekey_offload(sm); 1136252726Srpaulo 1137209158Srpaulo return; 1138209158Srpaulo 1139209158Srpaulofailed: 1140209158Srpaulo wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); 1141189251Ssam} 1142189251Ssam 1143189251Ssam 1144189251Ssamstatic int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm, 1145189251Ssam const u8 *keydata, 1146189251Ssam size_t keydatalen, 1147189251Ssam u16 key_info, 1148189251Ssam struct wpa_gtk_data *gd) 1149189251Ssam{ 1150189251Ssam int maxkeylen; 1151189251Ssam struct wpa_eapol_ie_parse ie; 1152189251Ssam 1153189251Ssam wpa_hexdump(MSG_DEBUG, "RSN: msg 1/2 key data", keydata, keydatalen); 1154252726Srpaulo if (wpa_supplicant_parse_ies(keydata, keydatalen, &ie) < 0) 1155252726Srpaulo return -1; 1156189251Ssam if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { 1157252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1158252726Srpaulo "WPA: GTK IE in unencrypted key data"); 1159189251Ssam return -1; 1160189251Ssam } 1161189251Ssam if (ie.gtk == NULL) { 1162252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 1163252726Srpaulo "WPA: No GTK IE in Group Key msg 1/2"); 1164189251Ssam return -1; 1165189251Ssam } 1166189251Ssam maxkeylen = gd->gtk_len = ie.gtk_len - 2; 1167189251Ssam 1168252726Srpaulo if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher, 1169189251Ssam gd->gtk_len, maxkeylen, 1170189251Ssam &gd->key_rsc_len, &gd->alg)) 1171189251Ssam return -1; 1172189251Ssam 1173189251Ssam wpa_hexdump(MSG_DEBUG, "RSN: received GTK in group key handshake", 1174189251Ssam ie.gtk, ie.gtk_len); 1175189251Ssam gd->keyidx = ie.gtk[0] & 0x3; 1176189251Ssam gd->tx = wpa_supplicant_gtk_tx_bit_workaround(sm, 1177189251Ssam !!(ie.gtk[0] & BIT(2))); 1178189251Ssam if (ie.gtk_len - 2 > sizeof(gd->gtk)) { 1179252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 1180252726Srpaulo "RSN: Too long GTK in GTK IE (len=%lu)", 1181252726Srpaulo (unsigned long) ie.gtk_len - 2); 1182189251Ssam return -1; 1183189251Ssam } 1184189251Ssam os_memcpy(gd->gtk, ie.gtk + 2, ie.gtk_len - 2); 1185189251Ssam 1186189251Ssam if (ieee80211w_set_keys(sm, &ie) < 0) 1187252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 1188252726Srpaulo "RSN: Failed to configure IGTK"); 1189189251Ssam 1190189251Ssam return 0; 1191189251Ssam} 1192189251Ssam 1193189251Ssam 1194189251Ssamstatic int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm, 1195189251Ssam const struct wpa_eapol_key *key, 1196189251Ssam size_t keydatalen, int key_info, 1197189251Ssam size_t extra_len, u16 ver, 1198189251Ssam struct wpa_gtk_data *gd) 1199189251Ssam{ 1200189251Ssam size_t maxkeylen; 1201189251Ssam u8 ek[32]; 1202189251Ssam 1203189251Ssam gd->gtk_len = WPA_GET_BE16(key->key_length); 1204189251Ssam maxkeylen = keydatalen; 1205189251Ssam if (keydatalen > extra_len) { 1206252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 1207252726Srpaulo "WPA: Truncated EAPOL-Key packet: " 1208252726Srpaulo "key_data_length=%lu > extra_len=%lu", 1209252726Srpaulo (unsigned long) keydatalen, (unsigned long) extra_len); 1210189251Ssam return -1; 1211189251Ssam } 1212189251Ssam if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { 1213189251Ssam if (maxkeylen < 8) { 1214252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 1215252726Srpaulo "WPA: Too short maxkeylen (%lu)", 1216252726Srpaulo (unsigned long) maxkeylen); 1217189251Ssam return -1; 1218189251Ssam } 1219189251Ssam maxkeylen -= 8; 1220189251Ssam } 1221189251Ssam 1222252726Srpaulo if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher, 1223189251Ssam gd->gtk_len, maxkeylen, 1224189251Ssam &gd->key_rsc_len, &gd->alg)) 1225189251Ssam return -1; 1226189251Ssam 1227189251Ssam gd->keyidx = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >> 1228189251Ssam WPA_KEY_INFO_KEY_INDEX_SHIFT; 1229189251Ssam if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) { 1230189251Ssam os_memcpy(ek, key->key_iv, 16); 1231189251Ssam os_memcpy(ek + 16, sm->ptk.kek, 16); 1232189251Ssam if (keydatalen > sizeof(gd->gtk)) { 1233252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1234252726Srpaulo "WPA: RC4 key data too long (%lu)", 1235252726Srpaulo (unsigned long) keydatalen); 1236189251Ssam return -1; 1237189251Ssam } 1238189251Ssam os_memcpy(gd->gtk, key + 1, keydatalen); 1239214734Srpaulo if (rc4_skip(ek, 32, 256, gd->gtk, keydatalen)) { 1240252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, 1241252726Srpaulo "WPA: RC4 failed"); 1242214734Srpaulo return -1; 1243214734Srpaulo } 1244189251Ssam } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { 1245189251Ssam if (keydatalen % 8) { 1246252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1247252726Srpaulo "WPA: Unsupported AES-WRAP len %lu", 1248252726Srpaulo (unsigned long) keydatalen); 1249189251Ssam return -1; 1250189251Ssam } 1251189251Ssam if (maxkeylen > sizeof(gd->gtk)) { 1252252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1253252726Srpaulo "WPA: AES-WRAP key data " 1254252726Srpaulo "too long (keydatalen=%lu maxkeylen=%lu)", 1255252726Srpaulo (unsigned long) keydatalen, 1256252726Srpaulo (unsigned long) maxkeylen); 1257189251Ssam return -1; 1258189251Ssam } 1259189251Ssam if (aes_unwrap(sm->ptk.kek, maxkeylen / 8, 1260189251Ssam (const u8 *) (key + 1), gd->gtk)) { 1261252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1262252726Srpaulo "WPA: AES unwrap failed - could not decrypt " 1263252726Srpaulo "GTK"); 1264189251Ssam return -1; 1265189251Ssam } 1266189251Ssam } else { 1267252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1268252726Srpaulo "WPA: Unsupported key_info type %d", ver); 1269189251Ssam return -1; 1270189251Ssam } 1271189251Ssam gd->tx = wpa_supplicant_gtk_tx_bit_workaround( 1272189251Ssam sm, !!(key_info & WPA_KEY_INFO_TXRX)); 1273189251Ssam return 0; 1274189251Ssam} 1275189251Ssam 1276189251Ssam 1277189251Ssamstatic int wpa_supplicant_send_2_of_2(struct wpa_sm *sm, 1278189251Ssam const struct wpa_eapol_key *key, 1279189251Ssam int ver, u16 key_info) 1280189251Ssam{ 1281189251Ssam size_t rlen; 1282189251Ssam struct wpa_eapol_key *reply; 1283189251Ssam u8 *rbuf; 1284189251Ssam 1285189251Ssam rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, 1286189251Ssam sizeof(*reply), &rlen, (void *) &reply); 1287189251Ssam if (rbuf == NULL) 1288189251Ssam return -1; 1289189251Ssam 1290189251Ssam reply->type = sm->proto == WPA_PROTO_RSN ? 1291189251Ssam EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; 1292189251Ssam key_info &= WPA_KEY_INFO_KEY_INDEX_MASK; 1293189251Ssam key_info |= ver | WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE; 1294189251Ssam WPA_PUT_BE16(reply->key_info, key_info); 1295189251Ssam if (sm->proto == WPA_PROTO_RSN) 1296189251Ssam WPA_PUT_BE16(reply->key_length, 0); 1297189251Ssam else 1298189251Ssam os_memcpy(reply->key_length, key->key_length, 2); 1299189251Ssam os_memcpy(reply->replay_counter, key->replay_counter, 1300189251Ssam WPA_REPLAY_COUNTER_LEN); 1301189251Ssam 1302189251Ssam WPA_PUT_BE16(reply->key_data_length, 0); 1303189251Ssam 1304252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/2"); 1305189251Ssam wpa_eapol_key_send(sm, sm->ptk.kck, ver, sm->bssid, ETH_P_EAPOL, 1306189251Ssam rbuf, rlen, reply->key_mic); 1307189251Ssam 1308189251Ssam return 0; 1309189251Ssam} 1310189251Ssam 1311189251Ssam 1312189251Ssamstatic void wpa_supplicant_process_1_of_2(struct wpa_sm *sm, 1313189251Ssam const unsigned char *src_addr, 1314189251Ssam const struct wpa_eapol_key *key, 1315189251Ssam int extra_len, u16 ver) 1316189251Ssam{ 1317189251Ssam u16 key_info, keydatalen; 1318189251Ssam int rekey, ret; 1319189251Ssam struct wpa_gtk_data gd; 1320189251Ssam 1321189251Ssam os_memset(&gd, 0, sizeof(gd)); 1322189251Ssam 1323189251Ssam rekey = wpa_sm_get_state(sm) == WPA_COMPLETED; 1324252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of Group Key " 1325252726Srpaulo "Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver); 1326189251Ssam 1327189251Ssam key_info = WPA_GET_BE16(key->key_info); 1328189251Ssam keydatalen = WPA_GET_BE16(key->key_data_length); 1329189251Ssam 1330189251Ssam if (sm->proto == WPA_PROTO_RSN) { 1331189251Ssam ret = wpa_supplicant_process_1_of_2_rsn(sm, 1332189251Ssam (const u8 *) (key + 1), 1333189251Ssam keydatalen, key_info, 1334189251Ssam &gd); 1335189251Ssam } else { 1336189251Ssam ret = wpa_supplicant_process_1_of_2_wpa(sm, key, keydatalen, 1337189251Ssam key_info, extra_len, 1338189251Ssam ver, &gd); 1339189251Ssam } 1340189251Ssam 1341189251Ssam wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE); 1342189251Ssam 1343189251Ssam if (ret) 1344209158Srpaulo goto failed; 1345189251Ssam 1346189251Ssam if (wpa_supplicant_install_gtk(sm, &gd, key->key_rsc) || 1347189251Ssam wpa_supplicant_send_2_of_2(sm, key, ver, key_info)) 1348209158Srpaulo goto failed; 1349189251Ssam 1350189251Ssam if (rekey) { 1351253040Shiren wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Group rekeying " 1352189251Ssam "completed with " MACSTR " [GTK=%s]", 1353189251Ssam MAC2STR(sm->bssid), wpa_cipher_txt(sm->group_cipher)); 1354189251Ssam wpa_sm_cancel_auth_timeout(sm); 1355189251Ssam wpa_sm_set_state(sm, WPA_COMPLETED); 1356252726Srpaulo 1357252726Srpaulo wpa_sm_set_rekey_offload(sm); 1358189251Ssam } else { 1359189251Ssam wpa_supplicant_key_neg_complete(sm, sm->bssid, 1360189251Ssam key_info & 1361189251Ssam WPA_KEY_INFO_SECURE); 1362189251Ssam } 1363209158Srpaulo return; 1364209158Srpaulo 1365209158Srpaulofailed: 1366209158Srpaulo wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); 1367189251Ssam} 1368189251Ssam 1369189251Ssam 1370189251Ssamstatic int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm, 1371189251Ssam struct wpa_eapol_key *key, 1372189251Ssam u16 ver, 1373189251Ssam const u8 *buf, size_t len) 1374189251Ssam{ 1375189251Ssam u8 mic[16]; 1376189251Ssam int ok = 0; 1377189251Ssam 1378189251Ssam os_memcpy(mic, key->key_mic, 16); 1379189251Ssam if (sm->tptk_set) { 1380189251Ssam os_memset(key->key_mic, 0, 16); 1381189251Ssam wpa_eapol_key_mic(sm->tptk.kck, ver, buf, len, 1382189251Ssam key->key_mic); 1383189251Ssam if (os_memcmp(mic, key->key_mic, 16) != 0) { 1384252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1385252726Srpaulo "WPA: Invalid EAPOL-Key MIC " 1386252726Srpaulo "when using TPTK - ignoring TPTK"); 1387189251Ssam } else { 1388189251Ssam ok = 1; 1389189251Ssam sm->tptk_set = 0; 1390189251Ssam sm->ptk_set = 1; 1391189251Ssam os_memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk)); 1392189251Ssam } 1393189251Ssam } 1394189251Ssam 1395189251Ssam if (!ok && sm->ptk_set) { 1396189251Ssam os_memset(key->key_mic, 0, 16); 1397189251Ssam wpa_eapol_key_mic(sm->ptk.kck, ver, buf, len, 1398189251Ssam key->key_mic); 1399189251Ssam if (os_memcmp(mic, key->key_mic, 16) != 0) { 1400252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1401252726Srpaulo "WPA: Invalid EAPOL-Key MIC - " 1402252726Srpaulo "dropping packet"); 1403189251Ssam return -1; 1404189251Ssam } 1405189251Ssam ok = 1; 1406189251Ssam } 1407189251Ssam 1408189251Ssam if (!ok) { 1409252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1410252726Srpaulo "WPA: Could not verify EAPOL-Key MIC - " 1411252726Srpaulo "dropping packet"); 1412189251Ssam return -1; 1413189251Ssam } 1414189251Ssam 1415189251Ssam os_memcpy(sm->rx_replay_counter, key->replay_counter, 1416189251Ssam WPA_REPLAY_COUNTER_LEN); 1417189251Ssam sm->rx_replay_counter_set = 1; 1418189251Ssam return 0; 1419189251Ssam} 1420189251Ssam 1421189251Ssam 1422189251Ssam/* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */ 1423189251Ssamstatic int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm, 1424189251Ssam struct wpa_eapol_key *key, u16 ver) 1425189251Ssam{ 1426189251Ssam u16 keydatalen = WPA_GET_BE16(key->key_data_length); 1427189251Ssam 1428189251Ssam wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data", 1429189251Ssam (u8 *) (key + 1), keydatalen); 1430189251Ssam if (!sm->ptk_set) { 1431252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1432252726Srpaulo "WPA: PTK not available, cannot decrypt EAPOL-Key Key " 1433252726Srpaulo "Data"); 1434189251Ssam return -1; 1435189251Ssam } 1436189251Ssam 1437189251Ssam /* Decrypt key data here so that this operation does not need 1438189251Ssam * to be implemented separately for each message type. */ 1439189251Ssam if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) { 1440189251Ssam u8 ek[32]; 1441189251Ssam os_memcpy(ek, key->key_iv, 16); 1442189251Ssam os_memcpy(ek + 16, sm->ptk.kek, 16); 1443214734Srpaulo if (rc4_skip(ek, 32, 256, (u8 *) (key + 1), keydatalen)) { 1444252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, 1445252726Srpaulo "WPA: RC4 failed"); 1446214734Srpaulo return -1; 1447214734Srpaulo } 1448189251Ssam } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || 1449189251Ssam ver == WPA_KEY_INFO_TYPE_AES_128_CMAC) { 1450189251Ssam u8 *buf; 1451189251Ssam if (keydatalen % 8) { 1452252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1453252726Srpaulo "WPA: Unsupported AES-WRAP len %d", 1454252726Srpaulo keydatalen); 1455189251Ssam return -1; 1456189251Ssam } 1457189251Ssam keydatalen -= 8; /* AES-WRAP adds 8 bytes */ 1458189251Ssam buf = os_malloc(keydatalen); 1459189251Ssam if (buf == NULL) { 1460252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1461252726Srpaulo "WPA: No memory for AES-UNWRAP buffer"); 1462189251Ssam return -1; 1463189251Ssam } 1464189251Ssam if (aes_unwrap(sm->ptk.kek, keydatalen / 8, 1465189251Ssam (u8 *) (key + 1), buf)) { 1466189251Ssam os_free(buf); 1467252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1468252726Srpaulo "WPA: AES unwrap failed - " 1469252726Srpaulo "could not decrypt EAPOL-Key key data"); 1470189251Ssam return -1; 1471189251Ssam } 1472189251Ssam os_memcpy(key + 1, buf, keydatalen); 1473189251Ssam os_free(buf); 1474189251Ssam WPA_PUT_BE16(key->key_data_length, keydatalen); 1475189251Ssam } else { 1476252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1477252726Srpaulo "WPA: Unsupported key_info type %d", ver); 1478189251Ssam return -1; 1479189251Ssam } 1480189251Ssam wpa_hexdump_key(MSG_DEBUG, "WPA: decrypted EAPOL-Key key data", 1481189251Ssam (u8 *) (key + 1), keydatalen); 1482189251Ssam return 0; 1483189251Ssam} 1484189251Ssam 1485189251Ssam 1486189251Ssam/** 1487189251Ssam * wpa_sm_aborted_cached - Notify WPA that PMKSA caching was aborted 1488189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 1489189251Ssam */ 1490189251Ssamvoid wpa_sm_aborted_cached(struct wpa_sm *sm) 1491189251Ssam{ 1492189251Ssam if (sm && sm->cur_pmksa) { 1493252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 1494252726Srpaulo "RSN: Cancelling PMKSA caching attempt"); 1495189251Ssam sm->cur_pmksa = NULL; 1496189251Ssam } 1497189251Ssam} 1498189251Ssam 1499189251Ssam 1500252726Srpaulostatic void wpa_eapol_key_dump(struct wpa_sm *sm, 1501252726Srpaulo const struct wpa_eapol_key *key) 1502189251Ssam{ 1503189251Ssam#ifndef CONFIG_NO_STDOUT_DEBUG 1504189251Ssam u16 key_info = WPA_GET_BE16(key->key_info); 1505189251Ssam 1506252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, " EAPOL-Key type=%d", key->type); 1507252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 1508252726Srpaulo " key_info 0x%x (ver=%d keyidx=%d rsvd=%d %s%s%s%s%s%s%s%s)", 1509252726Srpaulo key_info, key_info & WPA_KEY_INFO_TYPE_MASK, 1510252726Srpaulo (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >> 1511252726Srpaulo WPA_KEY_INFO_KEY_INDEX_SHIFT, 1512252726Srpaulo (key_info & (BIT(13) | BIT(14) | BIT(15))) >> 13, 1513252726Srpaulo key_info & WPA_KEY_INFO_KEY_TYPE ? "Pairwise" : "Group", 1514252726Srpaulo key_info & WPA_KEY_INFO_INSTALL ? " Install" : "", 1515252726Srpaulo key_info & WPA_KEY_INFO_ACK ? " Ack" : "", 1516252726Srpaulo key_info & WPA_KEY_INFO_MIC ? " MIC" : "", 1517252726Srpaulo key_info & WPA_KEY_INFO_SECURE ? " Secure" : "", 1518252726Srpaulo key_info & WPA_KEY_INFO_ERROR ? " Error" : "", 1519252726Srpaulo key_info & WPA_KEY_INFO_REQUEST ? " Request" : "", 1520252726Srpaulo key_info & WPA_KEY_INFO_ENCR_KEY_DATA ? " Encr" : ""); 1521252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 1522252726Srpaulo " key_length=%u key_data_length=%u", 1523252726Srpaulo WPA_GET_BE16(key->key_length), 1524252726Srpaulo WPA_GET_BE16(key->key_data_length)); 1525189251Ssam wpa_hexdump(MSG_DEBUG, " replay_counter", 1526189251Ssam key->replay_counter, WPA_REPLAY_COUNTER_LEN); 1527189251Ssam wpa_hexdump(MSG_DEBUG, " key_nonce", key->key_nonce, WPA_NONCE_LEN); 1528189251Ssam wpa_hexdump(MSG_DEBUG, " key_iv", key->key_iv, 16); 1529189251Ssam wpa_hexdump(MSG_DEBUG, " key_rsc", key->key_rsc, 8); 1530189251Ssam wpa_hexdump(MSG_DEBUG, " key_id (reserved)", key->key_id, 8); 1531189251Ssam wpa_hexdump(MSG_DEBUG, " key_mic", key->key_mic, 16); 1532189251Ssam#endif /* CONFIG_NO_STDOUT_DEBUG */ 1533189251Ssam} 1534189251Ssam 1535189251Ssam 1536189251Ssam/** 1537189251Ssam * wpa_sm_rx_eapol - Process received WPA EAPOL frames 1538189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 1539189251Ssam * @src_addr: Source MAC address of the EAPOL packet 1540189251Ssam * @buf: Pointer to the beginning of the EAPOL data (EAPOL header) 1541189251Ssam * @len: Length of the EAPOL frame 1542189251Ssam * Returns: 1 = WPA EAPOL-Key processed, 0 = not a WPA EAPOL-Key, -1 failure 1543189251Ssam * 1544189251Ssam * This function is called for each received EAPOL frame. Other than EAPOL-Key 1545189251Ssam * frames can be skipped if filtering is done elsewhere. wpa_sm_rx_eapol() is 1546189251Ssam * only processing WPA and WPA2 EAPOL-Key frames. 1547189251Ssam * 1548189251Ssam * The received EAPOL-Key packets are validated and valid packets are replied 1549189251Ssam * to. In addition, key material (PTK, GTK) is configured at the end of a 1550189251Ssam * successful key handshake. 1551189251Ssam */ 1552189251Ssamint wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, 1553189251Ssam const u8 *buf, size_t len) 1554189251Ssam{ 1555189251Ssam size_t plen, data_len, extra_len; 1556189251Ssam struct ieee802_1x_hdr *hdr; 1557189251Ssam struct wpa_eapol_key *key; 1558189251Ssam u16 key_info, ver; 1559189251Ssam u8 *tmp; 1560189251Ssam int ret = -1; 1561189251Ssam struct wpa_peerkey *peerkey = NULL; 1562189251Ssam 1563189251Ssam#ifdef CONFIG_IEEE80211R 1564189251Ssam sm->ft_completed = 0; 1565189251Ssam#endif /* CONFIG_IEEE80211R */ 1566189251Ssam 1567189251Ssam if (len < sizeof(*hdr) + sizeof(*key)) { 1568252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 1569252726Srpaulo "WPA: EAPOL frame too short to be a WPA " 1570252726Srpaulo "EAPOL-Key (len %lu, expecting at least %lu)", 1571252726Srpaulo (unsigned long) len, 1572252726Srpaulo (unsigned long) sizeof(*hdr) + sizeof(*key)); 1573189251Ssam return 0; 1574189251Ssam } 1575189251Ssam 1576189251Ssam tmp = os_malloc(len); 1577189251Ssam if (tmp == NULL) 1578189251Ssam return -1; 1579189251Ssam os_memcpy(tmp, buf, len); 1580189251Ssam 1581189251Ssam hdr = (struct ieee802_1x_hdr *) tmp; 1582189251Ssam key = (struct wpa_eapol_key *) (hdr + 1); 1583189251Ssam plen = be_to_host16(hdr->length); 1584189251Ssam data_len = plen + sizeof(*hdr); 1585252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 1586252726Srpaulo "IEEE 802.1X RX: version=%d type=%d length=%lu", 1587252726Srpaulo hdr->version, hdr->type, (unsigned long) plen); 1588189251Ssam 1589189251Ssam if (hdr->version < EAPOL_VERSION) { 1590189251Ssam /* TODO: backwards compatibility */ 1591189251Ssam } 1592189251Ssam if (hdr->type != IEEE802_1X_TYPE_EAPOL_KEY) { 1593252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 1594252726Srpaulo "WPA: EAPOL frame (type %u) discarded, " 1595189251Ssam "not a Key frame", hdr->type); 1596189251Ssam ret = 0; 1597189251Ssam goto out; 1598189251Ssam } 1599189251Ssam if (plen > len - sizeof(*hdr) || plen < sizeof(*key)) { 1600252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 1601252726Srpaulo "WPA: EAPOL frame payload size %lu " 1602252726Srpaulo "invalid (frame size %lu)", 1603252726Srpaulo (unsigned long) plen, (unsigned long) len); 1604189251Ssam ret = 0; 1605189251Ssam goto out; 1606189251Ssam } 1607189251Ssam 1608189251Ssam if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN) 1609189251Ssam { 1610252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 1611252726Srpaulo "WPA: EAPOL-Key type (%d) unknown, discarded", 1612252726Srpaulo key->type); 1613189251Ssam ret = 0; 1614189251Ssam goto out; 1615189251Ssam } 1616252726Srpaulo wpa_eapol_key_dump(sm, key); 1617189251Ssam 1618189251Ssam eapol_sm_notify_lower_layer_success(sm->eapol, 0); 1619189251Ssam wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL-Key", tmp, len); 1620189251Ssam if (data_len < len) { 1621252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 1622252726Srpaulo "WPA: ignoring %lu bytes after the IEEE 802.1X data", 1623252726Srpaulo (unsigned long) len - data_len); 1624189251Ssam } 1625189251Ssam key_info = WPA_GET_BE16(key->key_info); 1626189251Ssam ver = key_info & WPA_KEY_INFO_TYPE_MASK; 1627189251Ssam if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && 1628209158Srpaulo#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W) 1629189251Ssam ver != WPA_KEY_INFO_TYPE_AES_128_CMAC && 1630209158Srpaulo#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */ 1631189251Ssam ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { 1632252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 1633252726Srpaulo "WPA: Unsupported EAPOL-Key descriptor version %d", 1634252726Srpaulo ver); 1635189251Ssam goto out; 1636189251Ssam } 1637189251Ssam 1638189251Ssam#ifdef CONFIG_IEEE80211R 1639189251Ssam if (wpa_key_mgmt_ft(sm->key_mgmt)) { 1640189251Ssam /* IEEE 802.11r uses a new key_info type (AES-128-CMAC). */ 1641189251Ssam if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { 1642252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 1643252726Srpaulo "FT: AP did not use AES-128-CMAC"); 1644189251Ssam goto out; 1645189251Ssam } 1646189251Ssam } else 1647189251Ssam#endif /* CONFIG_IEEE80211R */ 1648189251Ssam#ifdef CONFIG_IEEE80211W 1649189251Ssam if (wpa_key_mgmt_sha256(sm->key_mgmt)) { 1650189251Ssam if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { 1651252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 1652252726Srpaulo "WPA: AP did not use the " 1653252726Srpaulo "negotiated AES-128-CMAC"); 1654189251Ssam goto out; 1655189251Ssam } 1656189251Ssam } else 1657189251Ssam#endif /* CONFIG_IEEE80211W */ 1658189251Ssam if (sm->pairwise_cipher == WPA_CIPHER_CCMP && 1659189251Ssam ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { 1660252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 1661252726Srpaulo "WPA: CCMP is used, but EAPOL-Key " 1662252726Srpaulo "descriptor version (%d) is not 2", ver); 1663189251Ssam if (sm->group_cipher != WPA_CIPHER_CCMP && 1664189251Ssam !(key_info & WPA_KEY_INFO_KEY_TYPE)) { 1665189251Ssam /* Earlier versions of IEEE 802.11i did not explicitly 1666189251Ssam * require version 2 descriptor for all EAPOL-Key 1667189251Ssam * packets, so allow group keys to use version 1 if 1668189251Ssam * CCMP is not used for them. */ 1669252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 1670252726Srpaulo "WPA: Backwards compatibility: allow invalid " 1671252726Srpaulo "version for non-CCMP group keys"); 1672189251Ssam } else 1673189251Ssam goto out; 1674189251Ssam } 1675252726Srpaulo if (sm->pairwise_cipher == WPA_CIPHER_GCMP && 1676252726Srpaulo ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { 1677252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 1678252726Srpaulo "WPA: GCMP is used, but EAPOL-Key " 1679252726Srpaulo "descriptor version (%d) is not 2", ver); 1680252726Srpaulo goto out; 1681252726Srpaulo } 1682189251Ssam 1683189251Ssam#ifdef CONFIG_PEERKEY 1684189251Ssam for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { 1685189251Ssam if (os_memcmp(peerkey->addr, src_addr, ETH_ALEN) == 0) 1686189251Ssam break; 1687189251Ssam } 1688189251Ssam 1689189251Ssam if (!(key_info & WPA_KEY_INFO_SMK_MESSAGE) && peerkey) { 1690189251Ssam if (!peerkey->initiator && peerkey->replay_counter_set && 1691189251Ssam os_memcmp(key->replay_counter, peerkey->replay_counter, 1692189251Ssam WPA_REPLAY_COUNTER_LEN) <= 0) { 1693252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1694252726Srpaulo "RSN: EAPOL-Key Replay Counter did not " 1695252726Srpaulo "increase (STK) - dropping packet"); 1696189251Ssam goto out; 1697189251Ssam } else if (peerkey->initiator) { 1698189251Ssam u8 _tmp[WPA_REPLAY_COUNTER_LEN]; 1699189251Ssam os_memcpy(_tmp, key->replay_counter, 1700189251Ssam WPA_REPLAY_COUNTER_LEN); 1701189251Ssam inc_byte_array(_tmp, WPA_REPLAY_COUNTER_LEN); 1702189251Ssam if (os_memcmp(_tmp, peerkey->replay_counter, 1703189251Ssam WPA_REPLAY_COUNTER_LEN) != 0) { 1704252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 1705252726Srpaulo "RSN: EAPOL-Key Replay " 1706252726Srpaulo "Counter did not match (STK) - " 1707252726Srpaulo "dropping packet"); 1708189251Ssam goto out; 1709189251Ssam } 1710189251Ssam } 1711189251Ssam } 1712189251Ssam 1713189251Ssam if (peerkey && peerkey->initiator && (key_info & WPA_KEY_INFO_ACK)) { 1714252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 1715252726Srpaulo "RSN: Ack bit in key_info from STK peer"); 1716189251Ssam goto out; 1717189251Ssam } 1718189251Ssam#endif /* CONFIG_PEERKEY */ 1719189251Ssam 1720189251Ssam if (!peerkey && sm->rx_replay_counter_set && 1721189251Ssam os_memcmp(key->replay_counter, sm->rx_replay_counter, 1722189251Ssam WPA_REPLAY_COUNTER_LEN) <= 0) { 1723252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1724252726Srpaulo "WPA: EAPOL-Key Replay Counter did not increase - " 1725252726Srpaulo "dropping packet"); 1726189251Ssam goto out; 1727189251Ssam } 1728189251Ssam 1729189251Ssam if (!(key_info & (WPA_KEY_INFO_ACK | WPA_KEY_INFO_SMK_MESSAGE)) 1730189251Ssam#ifdef CONFIG_PEERKEY 1731189251Ssam && (peerkey == NULL || !peerkey->initiator) 1732189251Ssam#endif /* CONFIG_PEERKEY */ 1733189251Ssam ) { 1734252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 1735252726Srpaulo "WPA: No Ack bit in key_info"); 1736189251Ssam goto out; 1737189251Ssam } 1738189251Ssam 1739189251Ssam if (key_info & WPA_KEY_INFO_REQUEST) { 1740252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 1741252726Srpaulo "WPA: EAPOL-Key with Request bit - dropped"); 1742189251Ssam goto out; 1743189251Ssam } 1744189251Ssam 1745189251Ssam if ((key_info & WPA_KEY_INFO_MIC) && !peerkey && 1746189251Ssam wpa_supplicant_verify_eapol_key_mic(sm, key, ver, tmp, data_len)) 1747189251Ssam goto out; 1748189251Ssam 1749189251Ssam#ifdef CONFIG_PEERKEY 1750189251Ssam if ((key_info & WPA_KEY_INFO_MIC) && peerkey && 1751189251Ssam peerkey_verify_eapol_key_mic(sm, peerkey, key, ver, tmp, data_len)) 1752189251Ssam goto out; 1753189251Ssam#endif /* CONFIG_PEERKEY */ 1754189251Ssam 1755189251Ssam extra_len = data_len - sizeof(*hdr) - sizeof(*key); 1756189251Ssam 1757189251Ssam if (WPA_GET_BE16(key->key_data_length) > extra_len) { 1758214734Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Invalid EAPOL-Key " 1759189251Ssam "frame - key_data overflow (%d > %lu)", 1760189251Ssam WPA_GET_BE16(key->key_data_length), 1761189251Ssam (unsigned long) extra_len); 1762189251Ssam goto out; 1763189251Ssam } 1764189251Ssam extra_len = WPA_GET_BE16(key->key_data_length); 1765189251Ssam 1766189251Ssam if (sm->proto == WPA_PROTO_RSN && 1767189251Ssam (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { 1768189251Ssam if (wpa_supplicant_decrypt_key_data(sm, key, ver)) 1769189251Ssam goto out; 1770189251Ssam extra_len = WPA_GET_BE16(key->key_data_length); 1771189251Ssam } 1772189251Ssam 1773189251Ssam if (key_info & WPA_KEY_INFO_KEY_TYPE) { 1774189251Ssam if (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) { 1775252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1776252726Srpaulo "WPA: Ignored EAPOL-Key (Pairwise) with " 1777252726Srpaulo "non-zero key index"); 1778189251Ssam goto out; 1779189251Ssam } 1780189251Ssam if (peerkey) { 1781189251Ssam /* PeerKey 4-Way Handshake */ 1782189251Ssam peerkey_rx_eapol_4way(sm, peerkey, key, key_info, ver); 1783189251Ssam } else if (key_info & WPA_KEY_INFO_MIC) { 1784189251Ssam /* 3/4 4-Way Handshake */ 1785189251Ssam wpa_supplicant_process_3_of_4(sm, key, ver); 1786189251Ssam } else { 1787189251Ssam /* 1/4 4-Way Handshake */ 1788189251Ssam wpa_supplicant_process_1_of_4(sm, src_addr, key, 1789189251Ssam ver); 1790189251Ssam } 1791189251Ssam } else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) { 1792189251Ssam /* PeerKey SMK Handshake */ 1793189251Ssam peerkey_rx_eapol_smk(sm, src_addr, key, extra_len, key_info, 1794189251Ssam ver); 1795189251Ssam } else { 1796189251Ssam if (key_info & WPA_KEY_INFO_MIC) { 1797189251Ssam /* 1/2 Group Key Handshake */ 1798189251Ssam wpa_supplicant_process_1_of_2(sm, src_addr, key, 1799189251Ssam extra_len, ver); 1800189251Ssam } else { 1801252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 1802252726Srpaulo "WPA: EAPOL-Key (Group) without Mic bit - " 1803252726Srpaulo "dropped"); 1804189251Ssam } 1805189251Ssam } 1806189251Ssam 1807189251Ssam ret = 1; 1808189251Ssam 1809189251Ssamout: 1810189251Ssam os_free(tmp); 1811189251Ssam return ret; 1812189251Ssam} 1813189251Ssam 1814189251Ssam 1815189251Ssam#ifdef CONFIG_CTRL_IFACE 1816189251Ssamstatic u32 wpa_key_mgmt_suite(struct wpa_sm *sm) 1817189251Ssam{ 1818189251Ssam switch (sm->key_mgmt) { 1819189251Ssam case WPA_KEY_MGMT_IEEE8021X: 1820189251Ssam return (sm->proto == WPA_PROTO_RSN ? 1821189251Ssam RSN_AUTH_KEY_MGMT_UNSPEC_802_1X : 1822189251Ssam WPA_AUTH_KEY_MGMT_UNSPEC_802_1X); 1823189251Ssam case WPA_KEY_MGMT_PSK: 1824189251Ssam return (sm->proto == WPA_PROTO_RSN ? 1825189251Ssam RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X : 1826189251Ssam WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X); 1827189251Ssam#ifdef CONFIG_IEEE80211R 1828189251Ssam case WPA_KEY_MGMT_FT_IEEE8021X: 1829189251Ssam return RSN_AUTH_KEY_MGMT_FT_802_1X; 1830189251Ssam case WPA_KEY_MGMT_FT_PSK: 1831189251Ssam return RSN_AUTH_KEY_MGMT_FT_PSK; 1832189251Ssam#endif /* CONFIG_IEEE80211R */ 1833189251Ssam#ifdef CONFIG_IEEE80211W 1834189251Ssam case WPA_KEY_MGMT_IEEE8021X_SHA256: 1835189251Ssam return RSN_AUTH_KEY_MGMT_802_1X_SHA256; 1836189251Ssam case WPA_KEY_MGMT_PSK_SHA256: 1837189251Ssam return RSN_AUTH_KEY_MGMT_PSK_SHA256; 1838189251Ssam#endif /* CONFIG_IEEE80211W */ 1839252726Srpaulo case WPA_KEY_MGMT_CCKM: 1840252726Srpaulo return (sm->proto == WPA_PROTO_RSN ? 1841252726Srpaulo RSN_AUTH_KEY_MGMT_CCKM: 1842252726Srpaulo WPA_AUTH_KEY_MGMT_CCKM); 1843189251Ssam case WPA_KEY_MGMT_WPA_NONE: 1844189251Ssam return WPA_AUTH_KEY_MGMT_NONE; 1845189251Ssam default: 1846189251Ssam return 0; 1847189251Ssam } 1848189251Ssam} 1849189251Ssam 1850189251Ssam 1851189251Ssam#define RSN_SUITE "%02x-%02x-%02x-%d" 1852189251Ssam#define RSN_SUITE_ARG(s) \ 1853189251Ssam((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff 1854189251Ssam 1855189251Ssam/** 1856189251Ssam * wpa_sm_get_mib - Dump text list of MIB entries 1857189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 1858189251Ssam * @buf: Buffer for the list 1859189251Ssam * @buflen: Length of the buffer 1860189251Ssam * Returns: Number of bytes written to buffer 1861189251Ssam * 1862189251Ssam * This function is used fetch dot11 MIB variables. 1863189251Ssam */ 1864189251Ssamint wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen) 1865189251Ssam{ 1866189251Ssam char pmkid_txt[PMKID_LEN * 2 + 1]; 1867189251Ssam int rsna, ret; 1868189251Ssam size_t len; 1869189251Ssam 1870189251Ssam if (sm->cur_pmksa) { 1871189251Ssam wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt), 1872189251Ssam sm->cur_pmksa->pmkid, PMKID_LEN); 1873189251Ssam } else 1874189251Ssam pmkid_txt[0] = '\0'; 1875189251Ssam 1876189251Ssam if ((wpa_key_mgmt_wpa_psk(sm->key_mgmt) || 1877189251Ssam wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) && 1878189251Ssam sm->proto == WPA_PROTO_RSN) 1879189251Ssam rsna = 1; 1880189251Ssam else 1881189251Ssam rsna = 0; 1882189251Ssam 1883189251Ssam ret = os_snprintf(buf, buflen, 1884189251Ssam "dot11RSNAOptionImplemented=TRUE\n" 1885189251Ssam "dot11RSNAPreauthenticationImplemented=TRUE\n" 1886189251Ssam "dot11RSNAEnabled=%s\n" 1887189251Ssam "dot11RSNAPreauthenticationEnabled=%s\n" 1888189251Ssam "dot11RSNAConfigVersion=%d\n" 1889189251Ssam "dot11RSNAConfigPairwiseKeysSupported=5\n" 1890189251Ssam "dot11RSNAConfigGroupCipherSize=%d\n" 1891189251Ssam "dot11RSNAConfigPMKLifetime=%d\n" 1892189251Ssam "dot11RSNAConfigPMKReauthThreshold=%d\n" 1893189251Ssam "dot11RSNAConfigNumberOfPTKSAReplayCounters=1\n" 1894189251Ssam "dot11RSNAConfigSATimeout=%d\n", 1895189251Ssam rsna ? "TRUE" : "FALSE", 1896189251Ssam rsna ? "TRUE" : "FALSE", 1897189251Ssam RSN_VERSION, 1898252726Srpaulo wpa_cipher_key_len(sm->group_cipher) * 8, 1899189251Ssam sm->dot11RSNAConfigPMKLifetime, 1900189251Ssam sm->dot11RSNAConfigPMKReauthThreshold, 1901189251Ssam sm->dot11RSNAConfigSATimeout); 1902189251Ssam if (ret < 0 || (size_t) ret >= buflen) 1903189251Ssam return 0; 1904189251Ssam len = ret; 1905189251Ssam 1906189251Ssam ret = os_snprintf( 1907189251Ssam buf + len, buflen - len, 1908189251Ssam "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n" 1909189251Ssam "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n" 1910189251Ssam "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n" 1911189251Ssam "dot11RSNAPMKIDUsed=%s\n" 1912189251Ssam "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n" 1913189251Ssam "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n" 1914189251Ssam "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n" 1915189251Ssam "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n" 1916189251Ssam "dot11RSNA4WayHandshakeFailures=%u\n", 1917189251Ssam RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)), 1918252726Srpaulo RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto, 1919252726Srpaulo sm->pairwise_cipher)), 1920252726Srpaulo RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto, 1921252726Srpaulo sm->group_cipher)), 1922189251Ssam pmkid_txt, 1923189251Ssam RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)), 1924252726Srpaulo RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto, 1925252726Srpaulo sm->pairwise_cipher)), 1926252726Srpaulo RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto, 1927252726Srpaulo sm->group_cipher)), 1928189251Ssam sm->dot11RSNA4WayHandshakeFailures); 1929189251Ssam if (ret >= 0 && (size_t) ret < buflen) 1930189251Ssam len += ret; 1931189251Ssam 1932189251Ssam return (int) len; 1933189251Ssam} 1934189251Ssam#endif /* CONFIG_CTRL_IFACE */ 1935189251Ssam 1936189251Ssam 1937189251Ssamstatic void wpa_sm_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry, 1938252726Srpaulo void *ctx, enum pmksa_free_reason reason) 1939189251Ssam{ 1940189251Ssam struct wpa_sm *sm = ctx; 1941252726Srpaulo int deauth = 0; 1942189251Ssam 1943252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA cache entry free_cb: " 1944252726Srpaulo MACSTR " reason=%d", MAC2STR(entry->aa), reason); 1945252726Srpaulo 1946252726Srpaulo if (sm->cur_pmksa == entry) { 1947252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 1948252726Srpaulo "RSN: %s current PMKSA entry", 1949252726Srpaulo reason == PMKSA_REPLACE ? "replaced" : "removed"); 1950252726Srpaulo pmksa_cache_clear_current(sm); 1951252726Srpaulo 1952252726Srpaulo /* 1953252726Srpaulo * If an entry is simply being replaced, there's no need to 1954252726Srpaulo * deauthenticate because it will be immediately re-added. 1955252726Srpaulo * This happens when EAP authentication is completed again 1956252726Srpaulo * (reauth or failed PMKSA caching attempt). 1957252726Srpaulo */ 1958252726Srpaulo if (reason != PMKSA_REPLACE) 1959252726Srpaulo deauth = 1; 1960252726Srpaulo } 1961252726Srpaulo 1962252726Srpaulo if (reason == PMKSA_EXPIRE && 1963189251Ssam (sm->pmk_len == entry->pmk_len && 1964189251Ssam os_memcmp(sm->pmk, entry->pmk, sm->pmk_len) == 0)) { 1965252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 1966252726Srpaulo "RSN: deauthenticating due to expired PMK"); 1967252726Srpaulo pmksa_cache_clear_current(sm); 1968252726Srpaulo deauth = 1; 1969252726Srpaulo } 1970189251Ssam 1971252726Srpaulo if (deauth) { 1972189251Ssam os_memset(sm->pmk, 0, sizeof(sm->pmk)); 1973189251Ssam wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); 1974189251Ssam } 1975189251Ssam} 1976189251Ssam 1977189251Ssam 1978189251Ssam/** 1979189251Ssam * wpa_sm_init - Initialize WPA state machine 1980189251Ssam * @ctx: Context pointer for callbacks; this needs to be an allocated buffer 1981189251Ssam * Returns: Pointer to the allocated WPA state machine data 1982189251Ssam * 1983189251Ssam * This function is used to allocate a new WPA state machine and the returned 1984189251Ssam * value is passed to all WPA state machine calls. 1985189251Ssam */ 1986189251Ssamstruct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx) 1987189251Ssam{ 1988189251Ssam struct wpa_sm *sm; 1989189251Ssam 1990189251Ssam sm = os_zalloc(sizeof(*sm)); 1991189251Ssam if (sm == NULL) 1992189251Ssam return NULL; 1993214734Srpaulo dl_list_init(&sm->pmksa_candidates); 1994189251Ssam sm->renew_snonce = 1; 1995189251Ssam sm->ctx = ctx; 1996189251Ssam 1997189251Ssam sm->dot11RSNAConfigPMKLifetime = 43200; 1998189251Ssam sm->dot11RSNAConfigPMKReauthThreshold = 70; 1999189251Ssam sm->dot11RSNAConfigSATimeout = 60; 2000189251Ssam 2001189251Ssam sm->pmksa = pmksa_cache_init(wpa_sm_pmksa_free_cb, sm, sm); 2002189251Ssam if (sm->pmksa == NULL) { 2003252726Srpaulo wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, 2004252726Srpaulo "RSN: PMKSA cache initialization failed"); 2005189251Ssam os_free(sm); 2006189251Ssam return NULL; 2007189251Ssam } 2008189251Ssam 2009189251Ssam return sm; 2010189251Ssam} 2011189251Ssam 2012189251Ssam 2013189251Ssam/** 2014189251Ssam * wpa_sm_deinit - Deinitialize WPA state machine 2015189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 2016189251Ssam */ 2017189251Ssamvoid wpa_sm_deinit(struct wpa_sm *sm) 2018189251Ssam{ 2019189251Ssam if (sm == NULL) 2020189251Ssam return; 2021189251Ssam pmksa_cache_deinit(sm->pmksa); 2022189251Ssam eloop_cancel_timeout(wpa_sm_start_preauth, sm, NULL); 2023189251Ssam eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL); 2024189251Ssam os_free(sm->assoc_wpa_ie); 2025189251Ssam os_free(sm->ap_wpa_ie); 2026189251Ssam os_free(sm->ap_rsn_ie); 2027189251Ssam os_free(sm->ctx); 2028189251Ssam peerkey_deinit(sm); 2029214734Srpaulo#ifdef CONFIG_IEEE80211R 2030214734Srpaulo os_free(sm->assoc_resp_ies); 2031214734Srpaulo#endif /* CONFIG_IEEE80211R */ 2032189251Ssam os_free(sm); 2033189251Ssam} 2034189251Ssam 2035189251Ssam 2036189251Ssam/** 2037189251Ssam * wpa_sm_notify_assoc - Notify WPA state machine about association 2038189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 2039189251Ssam * @bssid: The BSSID of the new association 2040189251Ssam * 2041189251Ssam * This function is called to let WPA state machine know that the connection 2042189251Ssam * was established. 2043189251Ssam */ 2044189251Ssamvoid wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid) 2045189251Ssam{ 2046189251Ssam int clear_ptk = 1; 2047189251Ssam 2048189251Ssam if (sm == NULL) 2049189251Ssam return; 2050189251Ssam 2051252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 2052252726Srpaulo "WPA: Association event - clear replay counter"); 2053189251Ssam os_memcpy(sm->bssid, bssid, ETH_ALEN); 2054189251Ssam os_memset(sm->rx_replay_counter, 0, WPA_REPLAY_COUNTER_LEN); 2055189251Ssam sm->rx_replay_counter_set = 0; 2056189251Ssam sm->renew_snonce = 1; 2057189251Ssam if (os_memcmp(sm->preauth_bssid, bssid, ETH_ALEN) == 0) 2058189251Ssam rsn_preauth_deinit(sm); 2059189251Ssam 2060189251Ssam#ifdef CONFIG_IEEE80211R 2061189251Ssam if (wpa_ft_is_completed(sm)) { 2062214734Srpaulo /* 2063214734Srpaulo * Clear portValid to kick EAPOL state machine to re-enter 2064214734Srpaulo * AUTHENTICATED state to get the EAPOL port Authorized. 2065214734Srpaulo */ 2066214734Srpaulo eapol_sm_notify_portValid(sm->eapol, FALSE); 2067189251Ssam wpa_supplicant_key_neg_complete(sm, sm->bssid, 1); 2068189251Ssam 2069189251Ssam /* Prepare for the next transition */ 2070214734Srpaulo wpa_ft_prepare_auth_request(sm, NULL); 2071189251Ssam 2072189251Ssam clear_ptk = 0; 2073189251Ssam } 2074189251Ssam#endif /* CONFIG_IEEE80211R */ 2075189251Ssam 2076189251Ssam if (clear_ptk) { 2077189251Ssam /* 2078189251Ssam * IEEE 802.11, 8.4.10: Delete PTK SA on (re)association if 2079189251Ssam * this is not part of a Fast BSS Transition. 2080189251Ssam */ 2081252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PTK"); 2082189251Ssam sm->ptk_set = 0; 2083189251Ssam sm->tptk_set = 0; 2084189251Ssam } 2085252726Srpaulo 2086252726Srpaulo#ifdef CONFIG_TDLS 2087252726Srpaulo wpa_tdls_assoc(sm); 2088252726Srpaulo#endif /* CONFIG_TDLS */ 2089189251Ssam} 2090189251Ssam 2091189251Ssam 2092189251Ssam/** 2093189251Ssam * wpa_sm_notify_disassoc - Notify WPA state machine about disassociation 2094189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 2095189251Ssam * 2096189251Ssam * This function is called to let WPA state machine know that the connection 2097189251Ssam * was lost. This will abort any existing pre-authentication session. 2098189251Ssam */ 2099189251Ssamvoid wpa_sm_notify_disassoc(struct wpa_sm *sm) 2100189251Ssam{ 2101189251Ssam rsn_preauth_deinit(sm); 2102252726Srpaulo pmksa_cache_clear_current(sm); 2103189251Ssam if (wpa_sm_get_state(sm) == WPA_4WAY_HANDSHAKE) 2104189251Ssam sm->dot11RSNA4WayHandshakeFailures++; 2105252726Srpaulo#ifdef CONFIG_TDLS 2106252726Srpaulo wpa_tdls_disassoc(sm); 2107252726Srpaulo#endif /* CONFIG_TDLS */ 2108189251Ssam} 2109189251Ssam 2110189251Ssam 2111189251Ssam/** 2112189251Ssam * wpa_sm_set_pmk - Set PMK 2113189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 2114189251Ssam * @pmk: The new PMK 2115189251Ssam * @pmk_len: The length of the new PMK in bytes 2116189251Ssam * 2117189251Ssam * Configure the PMK for WPA state machine. 2118189251Ssam */ 2119189251Ssamvoid wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len) 2120189251Ssam{ 2121189251Ssam if (sm == NULL) 2122189251Ssam return; 2123189251Ssam 2124189251Ssam sm->pmk_len = pmk_len; 2125189251Ssam os_memcpy(sm->pmk, pmk, pmk_len); 2126189251Ssam 2127189251Ssam#ifdef CONFIG_IEEE80211R 2128189251Ssam /* Set XXKey to be PSK for FT key derivation */ 2129189251Ssam sm->xxkey_len = pmk_len; 2130189251Ssam os_memcpy(sm->xxkey, pmk, pmk_len); 2131189251Ssam#endif /* CONFIG_IEEE80211R */ 2132189251Ssam} 2133189251Ssam 2134189251Ssam 2135189251Ssam/** 2136189251Ssam * wpa_sm_set_pmk_from_pmksa - Set PMK based on the current PMKSA 2137189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 2138189251Ssam * 2139189251Ssam * Take the PMK from the current PMKSA into use. If no PMKSA is active, the PMK 2140189251Ssam * will be cleared. 2141189251Ssam */ 2142189251Ssamvoid wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm) 2143189251Ssam{ 2144189251Ssam if (sm == NULL) 2145189251Ssam return; 2146189251Ssam 2147189251Ssam if (sm->cur_pmksa) { 2148189251Ssam sm->pmk_len = sm->cur_pmksa->pmk_len; 2149189251Ssam os_memcpy(sm->pmk, sm->cur_pmksa->pmk, sm->pmk_len); 2150189251Ssam } else { 2151189251Ssam sm->pmk_len = PMK_LEN; 2152189251Ssam os_memset(sm->pmk, 0, PMK_LEN); 2153189251Ssam } 2154189251Ssam} 2155189251Ssam 2156189251Ssam 2157189251Ssam/** 2158189251Ssam * wpa_sm_set_fast_reauth - Set fast reauthentication (EAP) enabled/disabled 2159189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 2160189251Ssam * @fast_reauth: Whether fast reauthentication (EAP) is allowed 2161189251Ssam */ 2162189251Ssamvoid wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth) 2163189251Ssam{ 2164189251Ssam if (sm) 2165189251Ssam sm->fast_reauth = fast_reauth; 2166189251Ssam} 2167189251Ssam 2168189251Ssam 2169189251Ssam/** 2170189251Ssam * wpa_sm_set_scard_ctx - Set context pointer for smartcard callbacks 2171189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 2172189251Ssam * @scard_ctx: Context pointer for smartcard related callback functions 2173189251Ssam */ 2174189251Ssamvoid wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx) 2175189251Ssam{ 2176189251Ssam if (sm == NULL) 2177189251Ssam return; 2178189251Ssam sm->scard_ctx = scard_ctx; 2179189251Ssam if (sm->preauth_eapol) 2180189251Ssam eapol_sm_register_scard_ctx(sm->preauth_eapol, scard_ctx); 2181189251Ssam} 2182189251Ssam 2183189251Ssam 2184189251Ssam/** 2185189251Ssam * wpa_sm_set_config - Notification of current configration change 2186189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 2187189251Ssam * @config: Pointer to current network configuration 2188189251Ssam * 2189189251Ssam * Notify WPA state machine that configuration has changed. config will be 2190189251Ssam * stored as a backpointer to network configuration. This can be %NULL to clear 2191189251Ssam * the stored pointed. 2192189251Ssam */ 2193189251Ssamvoid wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config) 2194189251Ssam{ 2195189251Ssam if (!sm) 2196189251Ssam return; 2197189251Ssam 2198189251Ssam if (config) { 2199189251Ssam sm->network_ctx = config->network_ctx; 2200189251Ssam sm->peerkey_enabled = config->peerkey_enabled; 2201189251Ssam sm->allowed_pairwise_cipher = config->allowed_pairwise_cipher; 2202189251Ssam sm->proactive_key_caching = config->proactive_key_caching; 2203189251Ssam sm->eap_workaround = config->eap_workaround; 2204189251Ssam sm->eap_conf_ctx = config->eap_conf_ctx; 2205189251Ssam if (config->ssid) { 2206189251Ssam os_memcpy(sm->ssid, config->ssid, config->ssid_len); 2207189251Ssam sm->ssid_len = config->ssid_len; 2208189251Ssam } else 2209189251Ssam sm->ssid_len = 0; 2210189251Ssam sm->wpa_ptk_rekey = config->wpa_ptk_rekey; 2211189251Ssam } else { 2212189251Ssam sm->network_ctx = NULL; 2213189251Ssam sm->peerkey_enabled = 0; 2214189251Ssam sm->allowed_pairwise_cipher = 0; 2215189251Ssam sm->proactive_key_caching = 0; 2216189251Ssam sm->eap_workaround = 0; 2217189251Ssam sm->eap_conf_ctx = NULL; 2218189251Ssam sm->ssid_len = 0; 2219189251Ssam sm->wpa_ptk_rekey = 0; 2220189251Ssam } 2221189251Ssam} 2222189251Ssam 2223189251Ssam 2224189251Ssam/** 2225189251Ssam * wpa_sm_set_own_addr - Set own MAC address 2226189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 2227189251Ssam * @addr: Own MAC address 2228189251Ssam */ 2229189251Ssamvoid wpa_sm_set_own_addr(struct wpa_sm *sm, const u8 *addr) 2230189251Ssam{ 2231189251Ssam if (sm) 2232189251Ssam os_memcpy(sm->own_addr, addr, ETH_ALEN); 2233189251Ssam} 2234189251Ssam 2235189251Ssam 2236189251Ssam/** 2237189251Ssam * wpa_sm_set_ifname - Set network interface name 2238189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 2239189251Ssam * @ifname: Interface name 2240189251Ssam * @bridge_ifname: Optional bridge interface name (for pre-auth) 2241189251Ssam */ 2242189251Ssamvoid wpa_sm_set_ifname(struct wpa_sm *sm, const char *ifname, 2243189251Ssam const char *bridge_ifname) 2244189251Ssam{ 2245189251Ssam if (sm) { 2246189251Ssam sm->ifname = ifname; 2247189251Ssam sm->bridge_ifname = bridge_ifname; 2248189251Ssam } 2249189251Ssam} 2250189251Ssam 2251189251Ssam 2252189251Ssam/** 2253189251Ssam * wpa_sm_set_eapol - Set EAPOL state machine pointer 2254189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 2255189251Ssam * @eapol: Pointer to EAPOL state machine allocated with eapol_sm_init() 2256189251Ssam */ 2257189251Ssamvoid wpa_sm_set_eapol(struct wpa_sm *sm, struct eapol_sm *eapol) 2258189251Ssam{ 2259189251Ssam if (sm) 2260189251Ssam sm->eapol = eapol; 2261189251Ssam} 2262189251Ssam 2263189251Ssam 2264189251Ssam/** 2265189251Ssam * wpa_sm_set_param - Set WPA state machine parameters 2266189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 2267189251Ssam * @param: Parameter field 2268189251Ssam * @value: Parameter value 2269189251Ssam * Returns: 0 on success, -1 on failure 2270189251Ssam */ 2271189251Ssamint wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, 2272189251Ssam unsigned int value) 2273189251Ssam{ 2274189251Ssam int ret = 0; 2275189251Ssam 2276189251Ssam if (sm == NULL) 2277189251Ssam return -1; 2278189251Ssam 2279189251Ssam switch (param) { 2280189251Ssam case RSNA_PMK_LIFETIME: 2281189251Ssam if (value > 0) 2282189251Ssam sm->dot11RSNAConfigPMKLifetime = value; 2283189251Ssam else 2284189251Ssam ret = -1; 2285189251Ssam break; 2286189251Ssam case RSNA_PMK_REAUTH_THRESHOLD: 2287189251Ssam if (value > 0 && value <= 100) 2288189251Ssam sm->dot11RSNAConfigPMKReauthThreshold = value; 2289189251Ssam else 2290189251Ssam ret = -1; 2291189251Ssam break; 2292189251Ssam case RSNA_SA_TIMEOUT: 2293189251Ssam if (value > 0) 2294189251Ssam sm->dot11RSNAConfigSATimeout = value; 2295189251Ssam else 2296189251Ssam ret = -1; 2297189251Ssam break; 2298189251Ssam case WPA_PARAM_PROTO: 2299189251Ssam sm->proto = value; 2300189251Ssam break; 2301189251Ssam case WPA_PARAM_PAIRWISE: 2302189251Ssam sm->pairwise_cipher = value; 2303189251Ssam break; 2304189251Ssam case WPA_PARAM_GROUP: 2305189251Ssam sm->group_cipher = value; 2306189251Ssam break; 2307189251Ssam case WPA_PARAM_KEY_MGMT: 2308189251Ssam sm->key_mgmt = value; 2309189251Ssam break; 2310189251Ssam#ifdef CONFIG_IEEE80211W 2311189251Ssam case WPA_PARAM_MGMT_GROUP: 2312189251Ssam sm->mgmt_group_cipher = value; 2313189251Ssam break; 2314189251Ssam#endif /* CONFIG_IEEE80211W */ 2315189251Ssam case WPA_PARAM_RSN_ENABLED: 2316189251Ssam sm->rsn_enabled = value; 2317189251Ssam break; 2318214734Srpaulo case WPA_PARAM_MFP: 2319214734Srpaulo sm->mfp = value; 2320214734Srpaulo break; 2321189251Ssam default: 2322189251Ssam break; 2323189251Ssam } 2324189251Ssam 2325189251Ssam return ret; 2326189251Ssam} 2327189251Ssam 2328189251Ssam 2329189251Ssam/** 2330189251Ssam * wpa_sm_get_param - Get WPA state machine parameters 2331189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 2332189251Ssam * @param: Parameter field 2333189251Ssam * Returns: Parameter value 2334189251Ssam */ 2335189251Ssamunsigned int wpa_sm_get_param(struct wpa_sm *sm, enum wpa_sm_conf_params param) 2336189251Ssam{ 2337189251Ssam if (sm == NULL) 2338189251Ssam return 0; 2339189251Ssam 2340189251Ssam switch (param) { 2341189251Ssam case RSNA_PMK_LIFETIME: 2342189251Ssam return sm->dot11RSNAConfigPMKLifetime; 2343189251Ssam case RSNA_PMK_REAUTH_THRESHOLD: 2344189251Ssam return sm->dot11RSNAConfigPMKReauthThreshold; 2345189251Ssam case RSNA_SA_TIMEOUT: 2346189251Ssam return sm->dot11RSNAConfigSATimeout; 2347189251Ssam case WPA_PARAM_PROTO: 2348189251Ssam return sm->proto; 2349189251Ssam case WPA_PARAM_PAIRWISE: 2350189251Ssam return sm->pairwise_cipher; 2351189251Ssam case WPA_PARAM_GROUP: 2352189251Ssam return sm->group_cipher; 2353189251Ssam case WPA_PARAM_KEY_MGMT: 2354189251Ssam return sm->key_mgmt; 2355189251Ssam#ifdef CONFIG_IEEE80211W 2356189251Ssam case WPA_PARAM_MGMT_GROUP: 2357189251Ssam return sm->mgmt_group_cipher; 2358189251Ssam#endif /* CONFIG_IEEE80211W */ 2359189251Ssam case WPA_PARAM_RSN_ENABLED: 2360189251Ssam return sm->rsn_enabled; 2361189251Ssam default: 2362189251Ssam return 0; 2363189251Ssam } 2364189251Ssam} 2365189251Ssam 2366189251Ssam 2367189251Ssam/** 2368189251Ssam * wpa_sm_get_status - Get WPA state machine 2369189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 2370189251Ssam * @buf: Buffer for status information 2371189251Ssam * @buflen: Maximum buffer length 2372189251Ssam * @verbose: Whether to include verbose status information 2373189251Ssam * Returns: Number of bytes written to buf. 2374189251Ssam * 2375189251Ssam * Query WPA state machine for status information. This function fills in 2376189251Ssam * a text area with current status information. If the buffer (buf) is not 2377189251Ssam * large enough, status information will be truncated to fit the buffer. 2378189251Ssam */ 2379189251Ssamint wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen, 2380189251Ssam int verbose) 2381189251Ssam{ 2382189251Ssam char *pos = buf, *end = buf + buflen; 2383189251Ssam int ret; 2384189251Ssam 2385189251Ssam ret = os_snprintf(pos, end - pos, 2386189251Ssam "pairwise_cipher=%s\n" 2387189251Ssam "group_cipher=%s\n" 2388189251Ssam "key_mgmt=%s\n", 2389189251Ssam wpa_cipher_txt(sm->pairwise_cipher), 2390189251Ssam wpa_cipher_txt(sm->group_cipher), 2391189251Ssam wpa_key_mgmt_txt(sm->key_mgmt, sm->proto)); 2392189251Ssam if (ret < 0 || ret >= end - pos) 2393189251Ssam return pos - buf; 2394189251Ssam pos += ret; 2395252726Srpaulo 2396252726Srpaulo if (sm->mfp != NO_MGMT_FRAME_PROTECTION && sm->ap_rsn_ie) { 2397252726Srpaulo struct wpa_ie_data rsn; 2398252726Srpaulo if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn) 2399252726Srpaulo >= 0 && 2400252726Srpaulo rsn.capabilities & (WPA_CAPABILITY_MFPR | 2401252726Srpaulo WPA_CAPABILITY_MFPC)) { 2402252726Srpaulo ret = os_snprintf(pos, end - pos, "pmf=%d\n", 2403252726Srpaulo (rsn.capabilities & 2404252726Srpaulo WPA_CAPABILITY_MFPR) ? 2 : 1); 2405252726Srpaulo if (ret < 0 || ret >= end - pos) 2406252726Srpaulo return pos - buf; 2407252726Srpaulo pos += ret; 2408252726Srpaulo } 2409252726Srpaulo } 2410252726Srpaulo 2411189251Ssam return pos - buf; 2412189251Ssam} 2413189251Ssam 2414189251Ssam 2415189251Ssam/** 2416189251Ssam * wpa_sm_set_assoc_wpa_ie_default - Generate own WPA/RSN IE from configuration 2417189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 2418189251Ssam * @wpa_ie: Pointer to buffer for WPA/RSN IE 2419189251Ssam * @wpa_ie_len: Pointer to the length of the wpa_ie buffer 2420189251Ssam * Returns: 0 on success, -1 on failure 2421189251Ssam */ 2422189251Ssamint wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie, 2423189251Ssam size_t *wpa_ie_len) 2424189251Ssam{ 2425189251Ssam int res; 2426189251Ssam 2427189251Ssam if (sm == NULL) 2428189251Ssam return -1; 2429189251Ssam 2430189251Ssam res = wpa_gen_wpa_ie(sm, wpa_ie, *wpa_ie_len); 2431189251Ssam if (res < 0) 2432189251Ssam return -1; 2433189251Ssam *wpa_ie_len = res; 2434189251Ssam 2435189251Ssam wpa_hexdump(MSG_DEBUG, "WPA: Set own WPA IE default", 2436189251Ssam wpa_ie, *wpa_ie_len); 2437189251Ssam 2438189251Ssam if (sm->assoc_wpa_ie == NULL) { 2439189251Ssam /* 2440189251Ssam * Make a copy of the WPA/RSN IE so that 4-Way Handshake gets 2441189251Ssam * the correct version of the IE even if PMKSA caching is 2442189251Ssam * aborted (which would remove PMKID from IE generation). 2443189251Ssam */ 2444189251Ssam sm->assoc_wpa_ie = os_malloc(*wpa_ie_len); 2445189251Ssam if (sm->assoc_wpa_ie == NULL) 2446189251Ssam return -1; 2447189251Ssam 2448189251Ssam os_memcpy(sm->assoc_wpa_ie, wpa_ie, *wpa_ie_len); 2449189251Ssam sm->assoc_wpa_ie_len = *wpa_ie_len; 2450189251Ssam } 2451189251Ssam 2452189251Ssam return 0; 2453189251Ssam} 2454189251Ssam 2455189251Ssam 2456189251Ssam/** 2457189251Ssam * wpa_sm_set_assoc_wpa_ie - Set own WPA/RSN IE from (Re)AssocReq 2458189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 2459189251Ssam * @ie: Pointer to IE data (starting from id) 2460189251Ssam * @len: IE length 2461189251Ssam * Returns: 0 on success, -1 on failure 2462189251Ssam * 2463189251Ssam * Inform WPA state machine about the WPA/RSN IE used in (Re)Association 2464189251Ssam * Request frame. The IE will be used to override the default value generated 2465189251Ssam * with wpa_sm_set_assoc_wpa_ie_default(). 2466189251Ssam */ 2467189251Ssamint wpa_sm_set_assoc_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len) 2468189251Ssam{ 2469189251Ssam if (sm == NULL) 2470189251Ssam return -1; 2471189251Ssam 2472189251Ssam os_free(sm->assoc_wpa_ie); 2473189251Ssam if (ie == NULL || len == 0) { 2474252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 2475252726Srpaulo "WPA: clearing own WPA/RSN IE"); 2476189251Ssam sm->assoc_wpa_ie = NULL; 2477189251Ssam sm->assoc_wpa_ie_len = 0; 2478189251Ssam } else { 2479189251Ssam wpa_hexdump(MSG_DEBUG, "WPA: set own WPA/RSN IE", ie, len); 2480189251Ssam sm->assoc_wpa_ie = os_malloc(len); 2481189251Ssam if (sm->assoc_wpa_ie == NULL) 2482189251Ssam return -1; 2483189251Ssam 2484189251Ssam os_memcpy(sm->assoc_wpa_ie, ie, len); 2485189251Ssam sm->assoc_wpa_ie_len = len; 2486189251Ssam } 2487189251Ssam 2488189251Ssam return 0; 2489189251Ssam} 2490189251Ssam 2491189251Ssam 2492189251Ssam/** 2493189251Ssam * wpa_sm_set_ap_wpa_ie - Set AP WPA IE from Beacon/ProbeResp 2494189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 2495189251Ssam * @ie: Pointer to IE data (starting from id) 2496189251Ssam * @len: IE length 2497189251Ssam * Returns: 0 on success, -1 on failure 2498189251Ssam * 2499189251Ssam * Inform WPA state machine about the WPA IE used in Beacon / Probe Response 2500189251Ssam * frame. 2501189251Ssam */ 2502189251Ssamint wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len) 2503189251Ssam{ 2504189251Ssam if (sm == NULL) 2505189251Ssam return -1; 2506189251Ssam 2507189251Ssam os_free(sm->ap_wpa_ie); 2508189251Ssam if (ie == NULL || len == 0) { 2509252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 2510252726Srpaulo "WPA: clearing AP WPA IE"); 2511189251Ssam sm->ap_wpa_ie = NULL; 2512189251Ssam sm->ap_wpa_ie_len = 0; 2513189251Ssam } else { 2514189251Ssam wpa_hexdump(MSG_DEBUG, "WPA: set AP WPA IE", ie, len); 2515189251Ssam sm->ap_wpa_ie = os_malloc(len); 2516189251Ssam if (sm->ap_wpa_ie == NULL) 2517189251Ssam return -1; 2518189251Ssam 2519189251Ssam os_memcpy(sm->ap_wpa_ie, ie, len); 2520189251Ssam sm->ap_wpa_ie_len = len; 2521189251Ssam } 2522189251Ssam 2523189251Ssam return 0; 2524189251Ssam} 2525189251Ssam 2526189251Ssam 2527189251Ssam/** 2528189251Ssam * wpa_sm_set_ap_rsn_ie - Set AP RSN IE from Beacon/ProbeResp 2529189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 2530189251Ssam * @ie: Pointer to IE data (starting from id) 2531189251Ssam * @len: IE length 2532189251Ssam * Returns: 0 on success, -1 on failure 2533189251Ssam * 2534189251Ssam * Inform WPA state machine about the RSN IE used in Beacon / Probe Response 2535189251Ssam * frame. 2536189251Ssam */ 2537189251Ssamint wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len) 2538189251Ssam{ 2539189251Ssam if (sm == NULL) 2540189251Ssam return -1; 2541189251Ssam 2542189251Ssam os_free(sm->ap_rsn_ie); 2543189251Ssam if (ie == NULL || len == 0) { 2544252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 2545252726Srpaulo "WPA: clearing AP RSN IE"); 2546189251Ssam sm->ap_rsn_ie = NULL; 2547189251Ssam sm->ap_rsn_ie_len = 0; 2548189251Ssam } else { 2549189251Ssam wpa_hexdump(MSG_DEBUG, "WPA: set AP RSN IE", ie, len); 2550189251Ssam sm->ap_rsn_ie = os_malloc(len); 2551189251Ssam if (sm->ap_rsn_ie == NULL) 2552189251Ssam return -1; 2553189251Ssam 2554189251Ssam os_memcpy(sm->ap_rsn_ie, ie, len); 2555189251Ssam sm->ap_rsn_ie_len = len; 2556189251Ssam } 2557189251Ssam 2558189251Ssam return 0; 2559189251Ssam} 2560189251Ssam 2561189251Ssam 2562189251Ssam/** 2563189251Ssam * wpa_sm_parse_own_wpa_ie - Parse own WPA/RSN IE 2564189251Ssam * @sm: Pointer to WPA state machine data from wpa_sm_init() 2565189251Ssam * @data: Pointer to data area for parsing results 2566189251Ssam * Returns: 0 on success, -1 if IE is not known, or -2 on parsing failure 2567189251Ssam * 2568189251Ssam * Parse the contents of the own WPA or RSN IE from (Re)AssocReq and write the 2569189251Ssam * parsed data into data. 2570189251Ssam */ 2571189251Ssamint wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, struct wpa_ie_data *data) 2572189251Ssam{ 2573252726Srpaulo if (sm == NULL) 2574189251Ssam return -1; 2575252726Srpaulo 2576252726Srpaulo if (sm->assoc_wpa_ie == NULL) { 2577252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, 2578252726Srpaulo "WPA: No WPA/RSN IE available from association info"); 2579252726Srpaulo return -1; 2580189251Ssam } 2581189251Ssam if (wpa_parse_wpa_ie(sm->assoc_wpa_ie, sm->assoc_wpa_ie_len, data)) 2582189251Ssam return -2; 2583189251Ssam return 0; 2584189251Ssam} 2585214734Srpaulo 2586214734Srpaulo 2587214734Srpauloint wpa_sm_pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len) 2588214734Srpaulo{ 2589214734Srpaulo#ifndef CONFIG_NO_WPA2 2590214734Srpaulo return pmksa_cache_list(sm->pmksa, buf, len); 2591214734Srpaulo#else /* CONFIG_NO_WPA2 */ 2592214734Srpaulo return -1; 2593214734Srpaulo#endif /* CONFIG_NO_WPA2 */ 2594214734Srpaulo} 2595214734Srpaulo 2596214734Srpaulo 2597214734Srpaulovoid wpa_sm_drop_sa(struct wpa_sm *sm) 2598214734Srpaulo{ 2599252726Srpaulo wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PMK and PTK"); 2600214734Srpaulo sm->ptk_set = 0; 2601214734Srpaulo sm->tptk_set = 0; 2602214734Srpaulo os_memset(sm->pmk, 0, sizeof(sm->pmk)); 2603214734Srpaulo os_memset(&sm->ptk, 0, sizeof(sm->ptk)); 2604214734Srpaulo os_memset(&sm->tptk, 0, sizeof(sm->tptk)); 2605214734Srpaulo} 2606214734Srpaulo 2607214734Srpaulo 2608214734Srpauloint wpa_sm_has_ptk(struct wpa_sm *sm) 2609214734Srpaulo{ 2610214734Srpaulo if (sm == NULL) 2611214734Srpaulo return 0; 2612214734Srpaulo return sm->ptk_set; 2613214734Srpaulo} 2614252726Srpaulo 2615252726Srpaulo 2616252726Srpaulovoid wpa_sm_update_replay_ctr(struct wpa_sm *sm, const u8 *replay_ctr) 2617252726Srpaulo{ 2618252726Srpaulo os_memcpy(sm->rx_replay_counter, replay_ctr, WPA_REPLAY_COUNTER_LEN); 2619252726Srpaulo} 2620252726Srpaulo 2621252726Srpaulo 2622252726Srpaulovoid wpa_sm_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx) 2623252726Srpaulo{ 2624252726Srpaulo#ifndef CONFIG_NO_WPA2 2625252726Srpaulo pmksa_cache_flush(sm->pmksa, network_ctx); 2626252726Srpaulo#endif /* CONFIG_NO_WPA2 */ 2627252726Srpaulo} 2628252726Srpaulo 2629252726Srpaulo 2630252726Srpaulo#ifdef CONFIG_WNM 2631252726Srpauloint wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf) 2632252726Srpaulo{ 2633252726Srpaulo struct wpa_gtk_data gd; 2634252726Srpaulo#ifdef CONFIG_IEEE80211W 2635252726Srpaulo struct wpa_igtk_kde igd; 2636252726Srpaulo u16 keyidx; 2637252726Srpaulo#endif /* CONFIG_IEEE80211W */ 2638252726Srpaulo u16 keyinfo; 2639252726Srpaulo u8 keylen; /* plaintext key len */ 2640252726Srpaulo u8 *key_rsc; 2641252726Srpaulo 2642252726Srpaulo os_memset(&gd, 0, sizeof(gd)); 2643252726Srpaulo#ifdef CONFIG_IEEE80211W 2644252726Srpaulo os_memset(&igd, 0, sizeof(igd)); 2645252726Srpaulo#endif /* CONFIG_IEEE80211W */ 2646252726Srpaulo 2647252726Srpaulo keylen = wpa_cipher_key_len(sm->group_cipher); 2648252726Srpaulo gd.key_rsc_len = wpa_cipher_rsc_len(sm->group_cipher); 2649252726Srpaulo gd.alg = wpa_cipher_to_alg(sm->group_cipher); 2650252726Srpaulo if (gd.alg == WPA_ALG_NONE) { 2651252726Srpaulo wpa_printf(MSG_DEBUG, "Unsupported group cipher suite"); 2652252726Srpaulo return -1; 2653252726Srpaulo } 2654252726Srpaulo 2655252726Srpaulo if (subelem_id == WNM_SLEEP_SUBELEM_GTK) { 2656252726Srpaulo key_rsc = buf + 5; 2657252726Srpaulo keyinfo = WPA_GET_LE16(buf + 2); 2658252726Srpaulo gd.gtk_len = keylen; 2659252726Srpaulo if (gd.gtk_len != buf[4]) { 2660252726Srpaulo wpa_printf(MSG_DEBUG, "GTK len mismatch len %d vs %d", 2661252726Srpaulo gd.gtk_len, buf[4]); 2662252726Srpaulo return -1; 2663252726Srpaulo } 2664252726Srpaulo gd.keyidx = keyinfo & 0x03; /* B0 - B1 */ 2665252726Srpaulo gd.tx = wpa_supplicant_gtk_tx_bit_workaround( 2666252726Srpaulo sm, !!(keyinfo & WPA_KEY_INFO_TXRX)); 2667252726Srpaulo 2668252726Srpaulo os_memcpy(gd.gtk, buf + 13, gd.gtk_len); 2669252726Srpaulo 2670252726Srpaulo wpa_hexdump_key(MSG_DEBUG, "Install GTK (WNM SLEEP)", 2671252726Srpaulo gd.gtk, gd.gtk_len); 2672252726Srpaulo if (wpa_supplicant_install_gtk(sm, &gd, key_rsc)) { 2673252726Srpaulo wpa_printf(MSG_DEBUG, "Failed to install the GTK in " 2674252726Srpaulo "WNM mode"); 2675252726Srpaulo return -1; 2676252726Srpaulo } 2677252726Srpaulo#ifdef CONFIG_IEEE80211W 2678252726Srpaulo } else if (subelem_id == WNM_SLEEP_SUBELEM_IGTK) { 2679252726Srpaulo os_memcpy(igd.keyid, buf + 2, 2); 2680252726Srpaulo os_memcpy(igd.pn, buf + 4, 6); 2681252726Srpaulo 2682252726Srpaulo keyidx = WPA_GET_LE16(igd.keyid); 2683252726Srpaulo os_memcpy(igd.igtk, buf + 10, WPA_IGTK_LEN); 2684252726Srpaulo 2685252726Srpaulo wpa_hexdump_key(MSG_DEBUG, "Install IGTK (WNM SLEEP)", 2686252726Srpaulo igd.igtk, WPA_IGTK_LEN); 2687252726Srpaulo if (wpa_sm_set_key(sm, WPA_ALG_IGTK, broadcast_ether_addr, 2688252726Srpaulo keyidx, 0, igd.pn, sizeof(igd.pn), 2689252726Srpaulo igd.igtk, WPA_IGTK_LEN) < 0) { 2690252726Srpaulo wpa_printf(MSG_DEBUG, "Failed to install the IGTK in " 2691252726Srpaulo "WNM mode"); 2692252726Srpaulo return -1; 2693252726Srpaulo } 2694252726Srpaulo#endif /* CONFIG_IEEE80211W */ 2695252726Srpaulo } else { 2696252726Srpaulo wpa_printf(MSG_DEBUG, "Unknown element id"); 2697252726Srpaulo return -1; 2698252726Srpaulo } 2699252726Srpaulo 2700252726Srpaulo return 0; 2701252726Srpaulo} 2702252726Srpaulo#endif /* CONFIG_WNM */ 2703