18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant - PeerKey for Direct Link Setup (DLS) 340b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha1.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha256.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_i.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_ie.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "peerkey.h" 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * wpa_add_ie(u8 *pos, const u8 *ie, size_t ie_len) 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, ie, ie_len); 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos + ie_len; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len) 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = WLAN_EID_VENDOR_SPECIFIC; 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = RSN_SELECTOR_LEN + data_len; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, kde); 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, data, data_len); 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += data_len; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_smk_timeout(void *eloop_ctx, void *timeout_ctx) 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm = eloop_ctx; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey = timeout_ctx; 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: time out SMK and any STK that was generated using this SMK */ 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_peerkey_free(struct wpa_sm *sm, 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey) 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_supplicant_smk_timeout, sm, peerkey); 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(peerkey); 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_send_smk_error(struct wpa_sm *sm, const u8 *dst, 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *peer, 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 mui, u16 error_type, int ver) 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rlen; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *err; 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_error_kde error; 699839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt u8 *rbuf, *pos, *mic; 709839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt size_t kde_len, mic_len = 16; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len = 2 + RSN_SELECTOR_LEN + sizeof(error); 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer) 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len += 2 + RSN_SELECTOR_LEN + ETH_ALEN; 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, 789839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt NULL, sizeof(*err) + mic_len + 2 + kde_len, 799839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt &rlen, (void *) &err); 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 829839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt mic = (u8 *) (err + 1); 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err->type = EAPOL_KEY_TYPE_RSN; 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_SECURE | WPA_KEY_INFO_ERROR | 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_REQUEST; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(err->key_info, key_info); 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(err->key_length, 0); 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(err->replay_counter, sm->request_counter, 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 949839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt WPA_PUT_BE16(mic + mic_len, (u16) kde_len); 959839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt pos = mic + mic_len + 2; 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer) { 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Peer MAC Address KDE */ 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN); 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Error KDE */ 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt error.mui = host_to_be16(mui); 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt error.error_type = host_to_be16(error_type); 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_add_kde(pos, RSN_KEY_DATA_ERROR, (u8 *) &error, sizeof(error)); 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer) { 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error (peer " 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " mui %d error_type %d)", 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peer), mui, error_type); 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error " 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(mui %d error_type %d)", mui, error_type); 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1169839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt wpa_eapol_key_send(sm, &sm->ptk, ver, dst, ETH_P_EAPOL, rbuf, rlen, 1179839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt mic); 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_send_smk_m3(struct wpa_sm *sm, 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ver, struct wpa_peerkey *peerkey) 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rlen; 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *reply; 1309839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt u8 *rbuf, *pos, *mic; 1319839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt size_t kde_len, mic_len = 16; 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info; 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* KDEs: Peer RSN IE, Initiator MAC Address, Initiator Nonce */ 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len = peerkey->rsnie_p_len + 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + RSN_SELECTOR_LEN + ETH_ALEN + 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN; 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, 1409839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt NULL, sizeof(*reply) + mic_len + 2 + kde_len, 1419839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt &rlen, (void *) &reply); 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply->type = EAPOL_KEY_TYPE_RSN; 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_SECURE; 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_info, key_info); 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_length, 0); 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply->replay_counter, key->replay_counter, 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply->key_nonce, peerkey->pnonce, WPA_NONCE_LEN); 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1559839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt mic = (u8 *) (reply + 1); 1569839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt WPA_PUT_BE16(mic + mic_len, (u16) kde_len); 1579839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt pos = mic + mic_len + 2; 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Peer RSN IE */ 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len); 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Initiator MAC Address KDE */ 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peerkey->addr, ETH_ALEN); 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Initiator Nonce */ 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_add_kde(pos, RSN_KEY_DATA_NONCE, peerkey->inonce, WPA_NONCE_LEN); 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK M3"); 1699839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt wpa_eapol_key_send(sm, &sm->ptk, ver, src_addr, ETH_P_EAPOL, rbuf, rlen, 1709839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt mic); 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_smk_m2( 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm, const unsigned char *src_addr, 178293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt const struct wpa_eapol_key *key, const u8 *key_data, 179293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt size_t key_data_len, int ver) 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey; 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data ie; 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int cipher; 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_ie_hdr *hdr; 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Received SMK M2"); 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) { 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: SMK handshake not allowed for " 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the current network"); 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 196293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt if (wpa_supplicant_parse_ies(key_data, key_data_len, &kde) < 0) { 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M2"); 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie == NULL || kde.mac_addr == NULL || 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.mac_addr_len < ETH_ALEN) { 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No RSN IE or MAC address KDE in " 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SMK M2"); 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: SMK M2 - SMK initiator " MACSTR, 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(kde.mac_addr)); 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie_len > PEERKEY_MAX_IE_LEN) { 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Too long Initiator RSN IE in SMK " 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "M2"); 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) { 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Failed to parse RSN IE in SMK M2"); 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 222a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt cipher = wpa_pick_pairwise_cipher(ie.pairwise_cipher & 223a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt sm->allowed_pairwise_cipher, 0); 224a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (cipher < 0) { 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No acceptable cipher in SMK M2"); 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_send_smk_error(sm, src_addr, kde.mac_addr, 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt STK_MUI_SMK, STK_ERR_CPHR_NS, 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver); 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 231a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Using %s for PeerKey", 232a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_cipher_txt(cipher)); 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: find existing entry and if found, use that instead of adding 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * a new one; how to handle the case where both ends initiate at the 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * same time? */ 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey = os_zalloc(sizeof(*peerkey)); 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey == NULL) 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->addr, kde.mac_addr, ETH_ALEN); 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN); 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->rsnie_i, kde.rsn_ie, kde.rsn_ie_len); 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_i_len = kde.rsn_ie_len; 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->cipher = cipher; 24540b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt peerkey->akmp = ie.key_mgmt; 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(peerkey->pnonce, WPA_NONCE_LEN)) { 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Failed to get random data for PNonce"); 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_peerkey_free(sm, peerkey); 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct rsn_ie_hdr *) peerkey->rsnie_p; 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->elem_id = WLAN_EID_RSN; 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(hdr->version, RSN_VERSION); 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (hdr + 1); 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Group Suite can be anything for SMK RSN IE; receiver will just 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ignore it. */ 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Include only the selected cipher in pairwise cipher suite */ 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, 1); 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 2654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN, cipher)); 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->len = (pos - peerkey->rsnie_p) - 2; 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_p_len = pos - peerkey->rsnie_p; 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake", 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_p, peerkey->rsnie_p_len); 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_send_smk_m3(sm, src_addr, key, ver, peerkey); 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->next = sm->peerkey; 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->peerkey = peerkey; 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rsn_smkid - Derive SMK identifier 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @smk: Station master key (32 bytes) 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pnonce: Peer Nonce 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mac_p: Peer MAC address 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @inonce: Initiator Nonce 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mac_i: Initiator MAC address 28940b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * @akmp: Negotiated AKM 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8.5.1.4 Station to station (STK) key hierarchy 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SMKID = HMAC-SHA1-128(SMK, "SMK Name" || PNonce || MAC_P || INonce || MAC_I) 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void rsn_smkid(const u8 *smk, const u8 *pnonce, const u8 *mac_p, 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *inonce, const u8 *mac_i, u8 *smkid, 29640b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt int akmp) 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *title = "SMK Name"; 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[5]; 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const size_t len[5] = { 8, WPA_NONCE_LEN, ETH_ALEN, WPA_NONCE_LEN, 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ETH_ALEN }; 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned char hash[SHA256_MAC_LEN]; 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = (u8 *) title; 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = pnonce; 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = mac_p; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[3] = inonce; 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[4] = mac_i; 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 31140b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt if (wpa_key_mgmt_sha256(akmp)) 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha256_vector(smk, PMK_LEN, 5, addr, len, hash); 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha1_vector(smk, PMK_LEN, 5, addr, len, hash); 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(smkid, hash, PMKID_LEN); 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_send_stk_1_of_4(struct wpa_sm *sm, 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey) 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t mlen; 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *msg; 3259839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt u8 *mbuf, *mic; 3269839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt size_t kde_len, mic_len = 16; 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info, ver; 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN; 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, 3329839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt sizeof(*msg) + mic_len + 2 + kde_len, &mlen, 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (void *) &msg); 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mbuf == NULL) 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3379839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt mic = (u8 *) (msg + 1); 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg->type = EAPOL_KEY_TYPE_RSN; 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (peerkey->cipher != WPA_CIPHER_TKIP) 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK; 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(msg->key_info, key_info); 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (peerkey->cipher != WPA_CIPHER_TKIP) 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(msg->key_length, 16); 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(msg->key_length, 32); 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(msg->replay_counter, peerkey->replay_counter, 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN); 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3579839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt WPA_PUT_BE16(mic + mic_len, kde_len); 3589839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt wpa_add_kde(mic + mic_len + 2, RSN_KEY_DATA_PMKID, 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->smkid, PMKID_LEN); 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(peerkey->inonce, WPA_NONCE_LEN)) { 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: Failed to get random data for INonce (STK)"); 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(mbuf); 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: INonce for STK 4-Way Handshake", 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->inonce, WPA_NONCE_LEN); 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN); 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 1/4 to " MACSTR, 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peerkey->addr)); 3739839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt wpa_eapol_key_send(sm, NULL, ver, peerkey->addr, ETH_P_EAPOL, 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mbuf, mlen, NULL); 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_send_stk_3_of_4(struct wpa_sm *sm, 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey) 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t mlen; 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *msg; 3839839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt u8 *mbuf, *pos, *mic; 3849839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt size_t kde_len, mic_len = 16; 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info, ver; 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt be32 lifetime; 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len = peerkey->rsnie_i_len + 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + RSN_SELECTOR_LEN + sizeof(lifetime); 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, 3929839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt sizeof(*msg) + mic_len + 2 + kde_len, &mlen, 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (void *) &msg); 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mbuf == NULL) 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3979839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt mic = (u8 *) (msg + 1); 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg->type = EAPOL_KEY_TYPE_RSN; 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (peerkey->cipher != WPA_CIPHER_TKIP) 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK | 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE; 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(msg->key_info, key_info); 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (peerkey->cipher != WPA_CIPHER_TKIP) 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(msg->key_length, 16); 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(msg->key_length, 32); 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(msg->replay_counter, peerkey->replay_counter, 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN); 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4189839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt WPA_PUT_BE16(mic + mic_len, kde_len); 419293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt pos = mic + mic_len + 2; 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len); 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = host_to_be32(peerkey->lifetime); 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME, 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &lifetime, sizeof(lifetime)); 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN); 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 3/4 to " MACSTR, 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peerkey->addr)); 4299839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt wpa_eapol_key_send(sm, &peerkey->stk, ver, peerkey->addr, ETH_P_EAPOL, 4309839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt mbuf, mlen, mic); 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_smk_m4(struct wpa_peerkey *peerkey, 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *kde) 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Received SMK M4 (Initiator " MACSTR ")", 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(kde->mac_addr)); 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(kde->smk + PMK_LEN, peerkey->pnonce, WPA_NONCE_LEN) != 0) 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: PNonce in SMK KDE does not " 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "match with the one used in SMK M3"); 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(kde->nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) { 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: INonce in SMK M4 did not " 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "match with the one received in SMK M2"); 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_smk_m5(struct wpa_sm *sm, 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ver, 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey, 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *kde) 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int cipher; 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data ie; 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Received SMK M5 (Peer " MACSTR ")", 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(kde->mac_addr)); 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde->rsn_ie == NULL || kde->rsn_ie_len > PEERKEY_MAX_IE_LEN || 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0) { 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No RSN IE in SMK M5"); 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: abort negotiation */ 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(key->key_nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) { 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Key Nonce in SMK M5 does " 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not match with INonce used in SMK M1"); 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(kde->smk + PMK_LEN, peerkey->inonce, WPA_NONCE_LEN) != 0) 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: INonce in SMK KDE does not " 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "match with the one used in SMK M1"); 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->rsnie_p, kde->rsn_ie, kde->rsn_ie_len); 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_p_len = kde->rsn_ie_len; 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->pnonce, kde->nonce, WPA_NONCE_LEN); 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 493a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt cipher = wpa_pick_pairwise_cipher(ie.pairwise_cipher & 494a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt sm->allowed_pairwise_cipher, 0); 495a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (cipher < 0) { 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: SMK Peer STA " MACSTR " selected " 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unacceptable cipher", MAC2STR(kde->mac_addr)); 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_send_smk_error(sm, src_addr, kde->mac_addr, 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt STK_MUI_SMK, STK_ERR_CPHR_NS, 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver); 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: abort negotiation */ 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 504a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Using %s for PeerKey", 505a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_cipher_txt(cipher)); 506a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt peerkey->cipher = cipher; 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_smk_m45( 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm, const unsigned char *src_addr, 514293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt const struct wpa_eapol_key *key, const u8 *key_data, 515293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt size_t key_data_len, int ver) 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey; 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime; 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) { 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for " 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the current network"); 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 527293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt if (wpa_supplicant_parse_ies(key_data, key_data_len, &kde) < 0) { 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M4/M5"); 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN || 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN || 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.smk == NULL || kde.smk_len < PMK_LEN + WPA_NONCE_LEN || 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.lifetime == NULL || kde.lifetime_len < 4) { 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No MAC Address, Nonce, SMK, or " 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Lifetime KDE in SMK M4/M5"); 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) == 0 && 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(peerkey->initiator ? peerkey->inonce : 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->pnonce, 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_nonce, WPA_NONCE_LEN) == 0) 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey == NULL) { 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No matching SMK handshake found " 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for SMK M4/M5: peer " MACSTR, 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(kde.mac_addr)); 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey->initiator) { 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_process_smk_m5(sm, src_addr, key, ver, 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey, &kde) < 0) 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_process_smk_m4(peerkey, &kde) < 0) 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->smk, kde.smk, PMK_LEN); 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->smk_complete = 1; 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", peerkey->smk, PMK_LEN); 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = WPA_GET_BE32(kde.lifetime); 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: SMK lifetime %u seconds", lifetime); 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (lifetime > 1000000000) 570fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt lifetime = 1000000000; /* avoid overflowing eloop time */ 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->lifetime = lifetime; 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout, 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, peerkey); 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey->initiator) { 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_smkid(peerkey->smk, peerkey->pnonce, peerkey->addr, 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->inonce, sm->own_addr, peerkey->smkid, 57840b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt peerkey->akmp); 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_send_stk_1_of_4(sm, peerkey); 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_smkid(peerkey->smk, peerkey->pnonce, sm->own_addr, 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->inonce, peerkey->addr, peerkey->smkid, 58340b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt peerkey->akmp); 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: SMKID", peerkey->smkid, PMKID_LEN); 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_smk_error( 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm, const unsigned char *src_addr, 593293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt const u8 *key_data, size_t key_data_len) 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_error_kde error; 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 peer[ETH_ALEN]; 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 error_type; 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Received SMK Error"); 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) { 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for " 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the current network"); 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 608293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt if (wpa_supplicant_parse_ies(key_data, key_data_len, &kde) < 0) { 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK Error"); 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.error == NULL || kde.error_len < sizeof(error)) { 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No Error KDE in SMK Error"); 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.mac_addr && kde.mac_addr_len >= ETH_ALEN) 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer, kde.mac_addr, ETH_ALEN); 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(peer, 0, ETH_ALEN); 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&error, kde.error, sizeof(error)); 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt error_type = be_to_host16(error.error_type); 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: SMK Error KDE received: MUI %d error_type %d peer " 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR, 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt be_to_host16(error.mui), error_type, 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peer)); 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.mac_addr && 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (error_type == STK_ERR_STA_NR || error_type == STK_ERR_STA_NRSN || 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt error_type == STK_ERR_CPHR_NS)) { 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey; 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) == 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey == NULL) { 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: No matching SMK handshake " 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "found for SMK Error"); 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: abort SMK/STK handshake and remove all related keys */ 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_stk_1_of_4(struct wpa_sm *sm, 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey, 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 655c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt u16 ver, const u8 *key_data, 656c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt size_t key_data_len) 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse ie; 659c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt size_t kde_buf_len; 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ptk *stk; 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 buf[8], *kde_buf, *pos; 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt be32 lifetime; 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: RX message 1 of STK 4-Way Handshake from " 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&ie, 0, sizeof(ie)); 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RSN: msg 1/4 should contain SMKID for the selected SMK */ 670c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", key_data, key_data_len); 671c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0 || 672c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt ie.pmkid == NULL) { 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: No SMKID in STK 1/4"); 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 676c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(ie.pmkid, peerkey->smkid, PMKID_LEN) != 0) { 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 1/4", 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie.pmkid, PMKID_LEN); 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(peerkey->pnonce, WPA_NONCE_LEN)) { 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: Failed to get random data for PNonce"); 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Renewed PNonce", 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->pnonce, WPA_NONCE_LEN); 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Calculate STK which will be stored as a temporary STK until it has 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * been verified when processing message 3/4. */ 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt stk = &peerkey->tstk; 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion", 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->own_addr, peerkey->addr, 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->pnonce, key->key_nonce, 69640b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt stk, peerkey->akmp, peerkey->cipher); 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Supplicant: swap tx/rx Mic keys */ 69840b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt os_memcpy(buf, &stk->tk[16], 8); 69940b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt os_memcpy(&stk->tk[16], &stk->tk[24], 8); 70040b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt os_memcpy(&stk->tk[24], buf, 8); 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->tstk_set = 1; 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_buf_len = peerkey->rsnie_p_len + 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + RSN_SELECTOR_LEN + sizeof(lifetime) + 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + RSN_SELECTOR_LEN + PMKID_LEN; 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_buf = os_malloc(kde_buf_len); 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde_buf == NULL) 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = kde_buf; 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len); 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = host_to_be32(peerkey->lifetime); 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME, 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &lifetime, sizeof(lifetime)); 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_add_kde(pos, RSN_KEY_DATA_PMKID, peerkey->smkid, PMKID_LEN); 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_send_2_of_4(sm, peerkey->addr, key, ver, 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->pnonce, kde_buf, kde_buf_len, 718293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt stk) < 0) { 719293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Failed to send STK message 2/4"); 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(kde_buf); 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(kde_buf); 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN); 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_update_smk_lifetime(struct wpa_sm *sm, 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey, 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *kde) 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime; 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde->lifetime == NULL || kde->lifetime_len < sizeof(lifetime)) 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = WPA_GET_BE32(kde->lifetime); 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (lifetime >= peerkey->lifetime) { 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Peer used SMK lifetime %u seconds " 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "which is larger than or equal to own value %u " 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "seconds - ignored", lifetime, peerkey->lifetime); 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Peer used shorter SMK lifetime %u seconds " 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(own was %u seconds) - updated", 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime, peerkey->lifetime); 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->lifetime = lifetime; 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_supplicant_smk_timeout, sm, peerkey); 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout, 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, peerkey); 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_stk_2_of_4(struct wpa_sm *sm, 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey, 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 761c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt u16 ver, const u8 *key_data, 762c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt size_t key_data_len) 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: RX message 2 of STK 4-Way Handshake from " 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&kde, 0, sizeof(kde)); 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RSN: msg 2/4 should contain SMKID for the selected SMK and RSN IE 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * from the peer. It may also include Lifetime KDE. */ 773c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: msg 2/4 key data", key_data, key_data_len); 774c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (wpa_supplicant_parse_ies(key_data, key_data_len, &kde) < 0 || 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.pmkid == NULL || kde.rsn_ie == NULL) { 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: No SMKID or RSN IE in STK 2/4"); 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 780c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(kde.pmkid, peerkey->smkid, PMKID_LEN) != 0) { 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 2/4", 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.pmkid, PMKID_LEN); 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie_len != peerkey->rsnie_p_len || 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(kde.rsn_ie, peerkey->rsnie_p, kde.rsn_ie_len) != 0) { 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Peer RSN IE in SMK and STK " 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "handshakes did not match"); 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Peer RSN IE in SMK handshake", 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_p, peerkey->rsnie_p_len); 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Peer RSN IE in STK handshake", 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.rsn_ie, kde.rsn_ie_len); 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_update_smk_lifetime(sm, peerkey, &kde); 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_send_stk_3_of_4(sm, peerkey); 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->pnonce, key->key_nonce, WPA_NONCE_LEN); 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_stk_3_of_4(struct wpa_sm *sm, 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey, 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 807c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt u16 ver, const u8 *key_data, 808c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt size_t key_data_len) 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 811c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt size_t key_len; 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *_key; 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 key_buf[32], rsc[6]; 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: RX message 3 of STK 4-Way Handshake from " 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&kde, 0, sizeof(kde)); 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RSN: msg 3/4 should contain Initiator RSN IE. It may also include 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Lifetime KDE. */ 822c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: msg 3/4 key data", key_data, key_data_len); 823c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (wpa_supplicant_parse_ies(key_data, key_data_len, &kde) < 0) { 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Failed to parse key data in " 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "STK 3/4"); 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie_len != peerkey->rsnie_i_len || 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(kde.rsn_ie, peerkey->rsnie_i, kde.rsn_ie_len) != 0) { 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Initiator RSN IE in SMK and STK " 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "handshakes did not match"); 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Initiator RSN IE in SMK " 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "handshake", 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_i, peerkey->rsnie_i_len); 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Initiator RSN IE in STK " 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "handshake", 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.rsn_ie, kde.rsn_ie_len); 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN) != 0) { 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: INonce from message 1 of STK " 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "4-Way Handshake differs from 3 of STK 4-Way " 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Handshake - drop packet (src=" MACSTR ")", 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peerkey->addr)); 847293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: INonce from message 1", 848293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt peerkey->inonce, WPA_NONCE_LEN); 849293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: INonce from message 3", 850293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt key->key_nonce, WPA_NONCE_LEN); 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_update_smk_lifetime(sm, peerkey, &kde); 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_send_4_of_4(sm, peerkey->addr, key, ver, 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_BE16(key->key_info), 858293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt &peerkey->stk) < 0) { 859293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Failed to send STK message 4/4"); 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 861293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt } 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 86340b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt _key = peerkey->stk.tk; 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey->cipher == WPA_CIPHER_TKIP) { 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Swap Tx/Rx keys for Michael MIC */ 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key_buf, _key, 16); 86740b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt os_memcpy(key_buf + 16, _key + 24, 8); 86840b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt os_memcpy(key_buf + 24, _key + 16, 8); 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _key = key_buf; 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_len = 32; 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_len = 16; 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(rsc, 0, 6); 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1, 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsc, sizeof(rsc), _key, key_len) < 0) { 87740b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt os_memset(key_buf, 0, sizeof(key_buf)); 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the " 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "driver."); 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 88240b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt os_memset(key_buf, 0, sizeof(key_buf)); 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_stk_4_of_4(struct wpa_sm *sm, 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey, 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 ver) 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rsc[6]; 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: RX message 4 of STK 4-Way Handshake from " 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(rsc, 0, 6); 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1, 89840b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt rsc, sizeof(rsc), peerkey->stk.tk, 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->cipher == WPA_CIPHER_TKIP ? 32 : 16) < 0) { 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the " 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "driver."); 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * peerkey_verify_eapol_key_mic - Verify PeerKey MIC 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peerkey: Pointer to the PeerKey data for the peer 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key: Pointer to the EAPOL-Key frame header 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ver: Version bits from EAPOL-Key Key Info 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Pointer to the beginning of EAPOL-Key frame 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Length of the EAPOL-Key frame 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint peerkey_verify_eapol_key_mic(struct wpa_sm *sm, 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey, 9199839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt struct wpa_eapol_key *key, u16 ver, 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9229839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN], *mic_pos; 92340b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt size_t mic_len = 16; 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ok = 0; 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey->initiator && !peerkey->stk_set) { 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion", 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->own_addr, peerkey->addr, 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->inonce, key->key_nonce, 93040b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt &peerkey->stk, peerkey->akmp, peerkey->cipher); 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->stk_set = 1; 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9349839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt mic_pos = (u8 *) (key + 1); 9359839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt os_memcpy(mic, mic_pos, mic_len); 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey->tstk_set) { 9379839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt os_memset(mic_pos, 0, mic_len); 93840b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt wpa_eapol_key_mic(peerkey->tstk.kck, peerkey->tstk.kck_len, 9399839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt sm->key_mgmt, ver, buf, len, mic_pos); 9409839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt if (os_memcmp_const(mic, mic_pos, mic_len) != 0) { 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC " 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "when using TSTK - ignoring TSTK"); 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ok = 1; 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->tstk_set = 0; 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->stk_set = 1; 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&peerkey->stk, &peerkey->tstk, 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(peerkey->stk)); 94940b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt os_memset(&peerkey->tstk, 0, sizeof(peerkey->tstk)); 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ok && peerkey->stk_set) { 9549839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt os_memset(mic_pos, 0, mic_len); 95540b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt wpa_eapol_key_mic(peerkey->stk.kck, peerkey->stk.kck_len, 9569839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt sm->key_mgmt, ver, buf, len, mic_pos); 9579839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt if (os_memcmp_const(mic, mic_pos, mic_len) != 0) { 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC " 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "- dropping packet"); 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ok = 1; 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ok) { 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Could not verify EAPOL-Key MIC " 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "- dropping packet"); 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->replay_counter, key->replay_counter, 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->replay_counter_set = 1; 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_stkstart - Send EAPOL-Key Request for STK handshake (STK M1) 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peer: MAC address of the peer STA 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, or -1 on failure 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Send an EAPOL-Key Request to the current authenticator to start STK 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * handshake with the peer. 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9899839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt size_t rlen, kde_len, mic_len; 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *req; 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int key_info, ver; 9929839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt u8 bssid[ETH_ALEN], *rbuf, *pos, *count_pos, *mic; 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 count; 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_ie_hdr *hdr; 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey; 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data ie; 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->proto != WPA_PROTO_RSN || !sm->ptk_set || !sm->peerkey_enabled) 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->ap_rsn_ie && 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &ie) == 0 && 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(ie.capabilities & WPA_CAPABILITY_PEERKEY_ENABLED)) { 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Current AP does not support STK"); 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10089839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt mic_len = wpa_mic_len(sm->key_mgmt); 100961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->pairwise_cipher != WPA_CIPHER_TKIP) 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_get_bssid(sm, bssid) < 0) { 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "Failed to read BSSID for EAPOL-Key " 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SMK M1"); 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: find existing entry and if found, use that instead of adding 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * a new one */ 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey = os_zalloc(sizeof(*peerkey)); 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey == NULL) 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->initiator = 1; 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->addr, peer, ETH_ALEN); 102740b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt peerkey->akmp = sm->key_mgmt; 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SMK M1: 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce, 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * MIC=MIC, DataKDs=(RSNIE_I, MAC_P KDE)) 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct rsn_ie_hdr *) peerkey->rsnie_i; 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->elem_id = WLAN_EID_RSN; 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(hdr->version, RSN_VERSION); 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (hdr + 1); 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Group Suite can be anything for SMK RSN IE; receiver will just 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ignore it. */ 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count_pos = pos; 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt count = rsn_cipher_put_suites(pos, sm->allowed_pairwise_cipher); 10464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt pos += count * RSN_SELECTOR_LEN; 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(count_pos, count); 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->len = (pos - peerkey->rsnie_i) - 2; 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_i_len = pos - peerkey->rsnie_i; 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake", 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_i, peerkey->rsnie_i_len); 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len = peerkey->rsnie_i_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN; 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, 10579839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt sizeof(*req) + mic_len + 2 + kde_len, &rlen, 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (void *) &req); 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) { 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_peerkey_free(sm, peerkey); 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req->type = EAPOL_KEY_TYPE_RSN; 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_SECURE | WPA_KEY_INFO_REQUEST | ver; 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(req->key_info, key_info); 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(req->key_length, 0); 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(req->replay_counter, sm->request_counter, 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(peerkey->inonce, WPA_NONCE_LEN)) { 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Failed to get random data for INonce"); 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rbuf); 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_peerkey_free(sm, peerkey); 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(req->key_nonce, peerkey->inonce, WPA_NONCE_LEN); 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: INonce for SMK handshake", 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req->key_nonce, WPA_NONCE_LEN); 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10849839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt mic = pos = (u8 *) (req + 1); 10859839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt pos += mic_len; 10869839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt WPA_PUT_BE16(pos, (u16) kde_len); 10879839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt pos += 2; 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Initiator RSN IE */ 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len); 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Peer MAC address KDE */ 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN); 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Sending EAPOL-Key SMK M1 Request (peer " 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR ")", MAC2STR(peer)); 10969839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt wpa_eapol_key_send(sm, &sm->ptk, ver, bssid, ETH_P_EAPOL, rbuf, rlen, 10979839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt mic); 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->next = sm->peerkey; 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->peerkey = peerkey; 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * peerkey_deinit - Free PeerKey values 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid peerkey_deinit(struct wpa_sm *sm) 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *prev, *peerkey = sm->peerkey; 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (peerkey) { 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = peerkey; 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey = peerkey->next; 1116fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_supplicant_peerkey_free(sm, prev); 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->peerkey = NULL; 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey, 1123c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt struct wpa_eapol_key *key, u16 key_info, u16 ver, 1124c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt const u8 *key_data, size_t key_data_len) 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((key_info & (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) == 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) { 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3/4 STK 4-Way Handshake */ 1129c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt wpa_supplicant_process_stk_3_of_4(sm, peerkey, key, ver, 1130c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt key_data, key_data_len); 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_info & WPA_KEY_INFO_ACK) { 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1/4 STK 4-Way Handshake */ 1133c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt wpa_supplicant_process_stk_1_of_4(sm, peerkey, key, ver, 1134c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt key_data, key_data_len); 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_info & WPA_KEY_INFO_SECURE) { 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4/4 STK 4-Way Handshake */ 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_process_stk_4_of_4(sm, peerkey, key, ver); 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2/4 STK 4-Way Handshake */ 1140c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt wpa_supplicant_process_stk_2_of_4(sm, peerkey, key, ver, 1141c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt key_data, key_data_len); 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid peerkey_rx_eapol_smk(struct wpa_sm *sm, const u8 *src_addr, 1147293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt struct wpa_eapol_key *key, const u8 *key_data, 1148293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt size_t key_data_len, 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info, u16 ver) 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_ERROR) { 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SMK Error */ 1153293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt wpa_supplicant_process_smk_error(sm, src_addr, key_data, 1154293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt key_data_len); 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_info & WPA_KEY_INFO_ACK) { 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SMK M2 */ 1157293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt wpa_supplicant_process_smk_m2(sm, src_addr, key, key_data, 1158293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt key_data_len, ver); 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SMK M4 or M5 */ 1161293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt wpa_supplicant_process_smk_m45(sm, src_addr, key, key_data, 1162293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt key_data_len, ver); 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 1167