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; 6840b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt struct wpa_eapol_key_192 *err192; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_error_kde error; 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rbuf, *pos; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t kde_len; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len = 2 + RSN_SELECTOR_LEN + sizeof(error); 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer) 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len += 2 + RSN_SELECTOR_LEN + ETH_ALEN; 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, sizeof(*err) + kde_len, &rlen, 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (void *) &err); 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8340b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt err192 = (struct wpa_eapol_key_192 *) err; 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err->type = EAPOL_KEY_TYPE_RSN; 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_SECURE | WPA_KEY_INFO_ERROR | 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_REQUEST; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(err->key_info, key_info); 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(err->key_length, 0); 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(err->replay_counter, sm->request_counter, 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(err->key_data_length, (u16) kde_len); 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (err + 1); 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer) { 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Peer MAC Address KDE */ 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN); 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Error KDE */ 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt error.mui = host_to_be16(mui); 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt error.error_type = host_to_be16(error_type); 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_add_kde(pos, RSN_KEY_DATA_ERROR, (u8 *) &error, sizeof(error)); 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer) { 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error (peer " 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " mui %d error_type %d)", 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peer), mui, error_type); 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error " 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(mui %d error_type %d)", mui, error_type); 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11740b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, dst, 11840b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt ETH_P_EAPOL, rbuf, rlen, err192->key_mic); 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_send_smk_m3(struct wpa_sm *sm, 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ver, struct wpa_peerkey *peerkey) 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rlen; 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *reply; 13140b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt struct wpa_eapol_key_192 *reply192; 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rbuf, *pos; 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t kde_len; 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info; 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* KDEs: Peer RSN IE, Initiator MAC Address, Initiator Nonce */ 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len = peerkey->rsnie_p_len + 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + RSN_SELECTOR_LEN + ETH_ALEN + 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, sizeof(*reply) + kde_len, &rlen, 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (void *) &reply); 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14640b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt reply192 = (struct wpa_eapol_key_192 *) reply; 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply->type = EAPOL_KEY_TYPE_RSN; 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_SECURE; 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_info, key_info); 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_length, 0); 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply->replay_counter, key->replay_counter, 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply->key_nonce, peerkey->pnonce, WPA_NONCE_LEN); 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_data_length, (u16) kde_len); 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (reply + 1); 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Peer RSN IE */ 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len); 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Initiator MAC Address KDE */ 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peerkey->addr, ETH_ALEN); 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Initiator Nonce */ 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_add_kde(pos, RSN_KEY_DATA_NONCE, peerkey->inonce, WPA_NONCE_LEN); 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK M3"); 17140b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, src_addr, 17240b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt ETH_P_EAPOL, rbuf, rlen, reply192->key_mic); 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_smk_m2( 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm, const unsigned char *src_addr, 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, size_t extra_len, int ver) 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey; 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data ie; 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int cipher; 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_ie_hdr *hdr; 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Received SMK M2"); 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) { 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: SMK handshake not allowed for " 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the current network"); 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) < 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) { 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M2"); 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie == NULL || kde.mac_addr == NULL || 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.mac_addr_len < ETH_ALEN) { 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No RSN IE or MAC address KDE in " 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SMK M2"); 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: SMK M2 - SMK initiator " MACSTR, 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(kde.mac_addr)); 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie_len > PEERKEY_MAX_IE_LEN) { 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Too long Initiator RSN IE in SMK " 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "M2"); 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) { 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Failed to parse RSN IE in SMK M2"); 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 224a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt cipher = wpa_pick_pairwise_cipher(ie.pairwise_cipher & 225a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt sm->allowed_pairwise_cipher, 0); 226a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (cipher < 0) { 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No acceptable cipher in SMK M2"); 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_send_smk_error(sm, src_addr, kde.mac_addr, 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt STK_MUI_SMK, STK_ERR_CPHR_NS, 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver); 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 233a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Using %s for PeerKey", 234a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_cipher_txt(cipher)); 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: find existing entry and if found, use that instead of adding 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * a new one; how to handle the case where both ends initiate at the 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * same time? */ 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey = os_zalloc(sizeof(*peerkey)); 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey == NULL) 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->addr, kde.mac_addr, ETH_ALEN); 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN); 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->rsnie_i, kde.rsn_ie, kde.rsn_ie_len); 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_i_len = kde.rsn_ie_len; 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->cipher = cipher; 24740b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt peerkey->akmp = ie.key_mgmt; 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(peerkey->pnonce, WPA_NONCE_LEN)) { 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Failed to get random data for PNonce"); 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_peerkey_free(sm, peerkey); 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct rsn_ie_hdr *) peerkey->rsnie_p; 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->elem_id = WLAN_EID_RSN; 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(hdr->version, RSN_VERSION); 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (hdr + 1); 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Group Suite can be anything for SMK RSN IE; receiver will just 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ignore it. */ 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Include only the selected cipher in pairwise cipher suite */ 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, 1); 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 2674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN, cipher)); 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->len = (pos - peerkey->rsnie_p) - 2; 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_p_len = pos - peerkey->rsnie_p; 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake", 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_p, peerkey->rsnie_p_len); 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_send_smk_m3(sm, src_addr, key, ver, peerkey); 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->next = sm->peerkey; 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->peerkey = peerkey; 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rsn_smkid - Derive SMK identifier 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @smk: Station master key (32 bytes) 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pnonce: Peer Nonce 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mac_p: Peer MAC address 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @inonce: Initiator Nonce 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mac_i: Initiator MAC address 29140b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * @akmp: Negotiated AKM 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8.5.1.4 Station to station (STK) key hierarchy 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SMKID = HMAC-SHA1-128(SMK, "SMK Name" || PNonce || MAC_P || INonce || MAC_I) 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void rsn_smkid(const u8 *smk, const u8 *pnonce, const u8 *mac_p, 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *inonce, const u8 *mac_i, u8 *smkid, 29840b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt int akmp) 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *title = "SMK Name"; 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[5]; 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const size_t len[5] = { 8, WPA_NONCE_LEN, ETH_ALEN, WPA_NONCE_LEN, 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ETH_ALEN }; 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned char hash[SHA256_MAC_LEN]; 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = (u8 *) title; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = pnonce; 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = mac_p; 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[3] = inonce; 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[4] = mac_i; 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 31340b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt if (wpa_key_mgmt_sha256(akmp)) 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha256_vector(smk, PMK_LEN, 5, addr, len, hash); 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha1_vector(smk, PMK_LEN, 5, addr, len, hash); 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(smkid, hash, PMKID_LEN); 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_send_stk_1_of_4(struct wpa_sm *sm, 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey) 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t mlen; 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *msg; 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *mbuf; 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t kde_len; 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info, ver; 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN; 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(*msg) + kde_len, &mlen, 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (void *) &msg); 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mbuf == NULL) 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg->type = EAPOL_KEY_TYPE_RSN; 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (peerkey->cipher != WPA_CIPHER_TKIP) 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK; 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(msg->key_info, key_info); 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (peerkey->cipher != WPA_CIPHER_TKIP) 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(msg->key_length, 16); 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(msg->key_length, 32); 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(msg->replay_counter, peerkey->replay_counter, 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN); 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(msg->key_data_length, kde_len); 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_add_kde((u8 *) (msg + 1), RSN_KEY_DATA_PMKID, 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->smkid, PMKID_LEN); 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(peerkey->inonce, WPA_NONCE_LEN)) { 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: Failed to get random data for INonce (STK)"); 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(mbuf); 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: INonce for STK 4-Way Handshake", 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->inonce, WPA_NONCE_LEN); 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN); 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 1/4 to " MACSTR, 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peerkey->addr)); 37440b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt wpa_eapol_key_send(sm, NULL, 0, ver, peerkey->addr, ETH_P_EAPOL, 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mbuf, mlen, NULL); 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_send_stk_3_of_4(struct wpa_sm *sm, 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey) 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t mlen; 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *msg; 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *mbuf, *pos; 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t kde_len; 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info, ver; 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt be32 lifetime; 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len = peerkey->rsnie_i_len + 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + RSN_SELECTOR_LEN + sizeof(lifetime); 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(*msg) + kde_len, &mlen, 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (void *) &msg); 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mbuf == NULL) 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 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 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(msg->key_data_length, kde_len); 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (msg + 1); 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)); 42940b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt wpa_eapol_key_send(sm, peerkey->stk.kck, peerkey->stk.kck_len, ver, 43040b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt peerkey->addr, ETH_P_EAPOL, mbuf, mlen, 43140b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt msg->key_mic); 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_smk_m4(struct wpa_peerkey *peerkey, 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *kde) 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Received SMK M4 (Initiator " MACSTR ")", 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(kde->mac_addr)); 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(kde->smk + PMK_LEN, peerkey->pnonce, WPA_NONCE_LEN) != 0) 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: PNonce in SMK KDE does not " 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "match with the one used in SMK M3"); 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(kde->nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) { 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: INonce in SMK M4 did not " 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "match with the one received in SMK M2"); 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_smk_m5(struct wpa_sm *sm, 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ver, 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey, 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *kde) 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int cipher; 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data ie; 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Received SMK M5 (Peer " MACSTR ")", 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(kde->mac_addr)); 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde->rsn_ie == NULL || kde->rsn_ie_len > PEERKEY_MAX_IE_LEN || 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0) { 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No RSN IE in SMK M5"); 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: abort negotiation */ 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(key->key_nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) { 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Key Nonce in SMK M5 does " 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not match with INonce used in SMK M1"); 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(kde->smk + PMK_LEN, peerkey->inonce, WPA_NONCE_LEN) != 0) 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: INonce in SMK KDE does not " 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "match with the one used in SMK M1"); 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->rsnie_p, kde->rsn_ie, kde->rsn_ie_len); 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_p_len = kde->rsn_ie_len; 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->pnonce, kde->nonce, WPA_NONCE_LEN); 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 494a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt cipher = wpa_pick_pairwise_cipher(ie.pairwise_cipher & 495a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt sm->allowed_pairwise_cipher, 0); 496a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (cipher < 0) { 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: SMK Peer STA " MACSTR " selected " 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unacceptable cipher", MAC2STR(kde->mac_addr)); 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_send_smk_error(sm, src_addr, kde->mac_addr, 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt STK_MUI_SMK, STK_ERR_CPHR_NS, 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver); 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: abort negotiation */ 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 505a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Using %s for PeerKey", 506a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_cipher_txt(cipher)); 507a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt peerkey->cipher = cipher; 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_smk_m45( 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm, const unsigned char *src_addr, 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, size_t extra_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 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) < 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) { 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M4/M5"); 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN || 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN || 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.smk == NULL || kde.smk_len < PMK_LEN + WPA_NONCE_LEN || 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.lifetime == NULL || kde.lifetime_len < 4) { 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No MAC Address, Nonce, SMK, or " 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Lifetime KDE in SMK M4/M5"); 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) == 0 && 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(peerkey->initiator ? peerkey->inonce : 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->pnonce, 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_nonce, WPA_NONCE_LEN) == 0) 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey == NULL) { 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No matching SMK handshake found " 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for SMK M4/M5: peer " MACSTR, 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(kde.mac_addr)); 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey->initiator) { 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_process_smk_m5(sm, src_addr, key, ver, 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey, &kde) < 0) 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_process_smk_m4(peerkey, &kde) < 0) 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->smk, kde.smk, PMK_LEN); 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->smk_complete = 1; 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", peerkey->smk, PMK_LEN); 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = WPA_GET_BE32(kde.lifetime); 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: SMK lifetime %u seconds", lifetime); 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (lifetime > 1000000000) 571fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt lifetime = 1000000000; /* avoid overflowing eloop time */ 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->lifetime = lifetime; 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout, 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, peerkey); 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey->initiator) { 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_smkid(peerkey->smk, peerkey->pnonce, peerkey->addr, 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->inonce, sm->own_addr, peerkey->smkid, 57940b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt peerkey->akmp); 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_send_stk_1_of_4(sm, peerkey); 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_smkid(peerkey->smk, peerkey->pnonce, sm->own_addr, 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->inonce, peerkey->addr, peerkey->smkid, 58440b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt peerkey->akmp); 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: SMKID", peerkey->smkid, PMKID_LEN); 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_smk_error( 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm, const unsigned char *src_addr, 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, size_t extra_len) 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_error_kde error; 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 peer[ETH_ALEN]; 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 error_type; 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Received SMK Error"); 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) { 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for " 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the current network"); 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) < 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) { 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK Error"); 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.error == NULL || kde.error_len < sizeof(error)) { 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No Error KDE in SMK Error"); 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.mac_addr && kde.mac_addr_len >= ETH_ALEN) 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer, kde.mac_addr, ETH_ALEN); 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(peer, 0, ETH_ALEN); 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&error, kde.error, sizeof(error)); 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt error_type = be_to_host16(error.error_type); 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: SMK Error KDE received: MUI %d error_type %d peer " 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR, 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt be_to_host16(error.mui), error_type, 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peer)); 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.mac_addr && 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (error_type == STK_ERR_STA_NR || error_type == STK_ERR_STA_NRSN || 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt error_type == STK_ERR_CPHR_NS)) { 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey; 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) == 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey == NULL) { 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: No matching SMK handshake " 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "found for SMK Error"); 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: abort SMK/STK handshake and remove all related keys */ 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_stk_1_of_4(struct wpa_sm *sm, 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey, 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 657c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt u16 ver, const u8 *key_data, 658c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt size_t key_data_len) 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse ie; 661c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt size_t kde_buf_len; 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ptk *stk; 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 buf[8], *kde_buf, *pos; 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt be32 lifetime; 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: RX message 1 of STK 4-Way Handshake from " 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&ie, 0, sizeof(ie)); 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RSN: msg 1/4 should contain SMKID for the selected SMK */ 672c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", key_data, key_data_len); 673c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0 || 674c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt ie.pmkid == NULL) { 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: No SMKID in STK 1/4"); 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 678c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(ie.pmkid, peerkey->smkid, PMKID_LEN) != 0) { 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 1/4", 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie.pmkid, PMKID_LEN); 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(peerkey->pnonce, WPA_NONCE_LEN)) { 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: Failed to get random data for PNonce"); 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Renewed PNonce", 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->pnonce, WPA_NONCE_LEN); 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Calculate STK which will be stored as a temporary STK until it has 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * been verified when processing message 3/4. */ 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt stk = &peerkey->tstk; 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion", 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->own_addr, peerkey->addr, 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->pnonce, key->key_nonce, 69840b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt stk, peerkey->akmp, peerkey->cipher); 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Supplicant: swap tx/rx Mic keys */ 70040b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt os_memcpy(buf, &stk->tk[16], 8); 70140b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt os_memcpy(&stk->tk[16], &stk->tk[24], 8); 70240b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt os_memcpy(&stk->tk[24], buf, 8); 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->tstk_set = 1; 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_buf_len = peerkey->rsnie_p_len + 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + RSN_SELECTOR_LEN + sizeof(lifetime) + 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + RSN_SELECTOR_LEN + PMKID_LEN; 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_buf = os_malloc(kde_buf_len); 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde_buf == NULL) 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = kde_buf; 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len); 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = host_to_be32(peerkey->lifetime); 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME, 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &lifetime, sizeof(lifetime)); 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_add_kde(pos, RSN_KEY_DATA_PMKID, peerkey->smkid, PMKID_LEN); 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_send_2_of_4(sm, peerkey->addr, key, ver, 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->pnonce, kde_buf, kde_buf_len, 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt stk)) { 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(kde_buf); 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(kde_buf); 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN); 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_update_smk_lifetime(struct wpa_sm *sm, 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey, 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *kde) 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime; 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde->lifetime == NULL || kde->lifetime_len < sizeof(lifetime)) 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = WPA_GET_BE32(kde->lifetime); 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (lifetime >= peerkey->lifetime) { 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Peer used SMK lifetime %u seconds " 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "which is larger than or equal to own value %u " 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "seconds - ignored", lifetime, peerkey->lifetime); 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Peer used shorter SMK lifetime %u seconds " 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(own was %u seconds) - updated", 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime, peerkey->lifetime); 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->lifetime = lifetime; 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_supplicant_smk_timeout, sm, peerkey); 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout, 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, peerkey); 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_stk_2_of_4(struct wpa_sm *sm, 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey, 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 762c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt u16 ver, const u8 *key_data, 763c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt size_t key_data_len) 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: RX message 2 of STK 4-Way Handshake from " 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&kde, 0, sizeof(kde)); 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RSN: msg 2/4 should contain SMKID for the selected SMK and RSN IE 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * from the peer. It may also include Lifetime KDE. */ 774c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: msg 2/4 key data", key_data, key_data_len); 775c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (wpa_supplicant_parse_ies(key_data, key_data_len, &kde) < 0 || 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.pmkid == NULL || kde.rsn_ie == NULL) { 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: No SMKID or RSN IE in STK 2/4"); 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 781c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(kde.pmkid, peerkey->smkid, PMKID_LEN) != 0) { 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 2/4", 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.pmkid, PMKID_LEN); 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie_len != peerkey->rsnie_p_len || 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(kde.rsn_ie, peerkey->rsnie_p, kde.rsn_ie_len) != 0) { 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Peer RSN IE in SMK and STK " 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "handshakes did not match"); 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Peer RSN IE in SMK handshake", 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_p, peerkey->rsnie_p_len); 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Peer RSN IE in STK handshake", 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.rsn_ie, kde.rsn_ie_len); 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_update_smk_lifetime(sm, peerkey, &kde); 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_send_stk_3_of_4(sm, peerkey); 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->pnonce, key->key_nonce, WPA_NONCE_LEN); 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_stk_3_of_4(struct wpa_sm *sm, 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey, 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 808c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt u16 ver, const u8 *key_data, 809c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt size_t key_data_len) 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 812c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt size_t key_len; 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *_key; 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 key_buf[32], rsc[6]; 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: RX message 3 of STK 4-Way Handshake from " 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&kde, 0, sizeof(kde)); 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RSN: msg 3/4 should contain Initiator RSN IE. It may also include 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Lifetime KDE. */ 823c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: msg 3/4 key data", key_data, key_data_len); 824c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (wpa_supplicant_parse_ies(key_data, key_data_len, &kde) < 0) { 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Failed to parse key data in " 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "STK 3/4"); 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie_len != peerkey->rsnie_i_len || 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(kde.rsn_ie, peerkey->rsnie_i, kde.rsn_ie_len) != 0) { 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Initiator RSN IE in SMK and STK " 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "handshakes did not match"); 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Initiator RSN IE in SMK " 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "handshake", 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_i, peerkey->rsnie_i_len); 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Initiator RSN IE in STK " 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "handshake", 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.rsn_ie, kde.rsn_ie_len); 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN) != 0) { 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: INonce from message 1 of STK " 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "4-Way Handshake differs from 3 of STK 4-Way " 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Handshake - drop packet (src=" MACSTR ")", 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peerkey->addr)); 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_update_smk_lifetime(sm, peerkey, &kde); 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_send_4_of_4(sm, peerkey->addr, key, ver, 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_BE16(key->key_info), 85521de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt &peerkey->stk)) 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 85840b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt _key = peerkey->stk.tk; 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey->cipher == WPA_CIPHER_TKIP) { 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Swap Tx/Rx keys for Michael MIC */ 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key_buf, _key, 16); 86240b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt os_memcpy(key_buf + 16, _key + 24, 8); 86340b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt os_memcpy(key_buf + 24, _key + 16, 8); 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _key = key_buf; 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_len = 32; 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_len = 16; 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(rsc, 0, 6); 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1, 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsc, sizeof(rsc), _key, key_len) < 0) { 87240b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt os_memset(key_buf, 0, sizeof(key_buf)); 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the " 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "driver."); 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 87740b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt os_memset(key_buf, 0, sizeof(key_buf)); 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_stk_4_of_4(struct wpa_sm *sm, 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey, 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 ver) 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rsc[6]; 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: RX message 4 of STK 4-Way Handshake from " 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(rsc, 0, 6); 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1, 89340b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt rsc, sizeof(rsc), peerkey->stk.tk, 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->cipher == WPA_CIPHER_TKIP ? 32 : 16) < 0) { 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the " 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "driver."); 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * peerkey_verify_eapol_key_mic - Verify PeerKey MIC 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peerkey: Pointer to the PeerKey data for the peer 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key: Pointer to the EAPOL-Key frame header 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ver: Version bits from EAPOL-Key Key Info 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Pointer to the beginning of EAPOL-Key frame 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Length of the EAPOL-Key frame 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint peerkey_verify_eapol_key_mic(struct wpa_sm *sm, 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey, 91440b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt struct wpa_eapol_key_192 *key, u16 ver, 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 91740b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; 91840b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt size_t mic_len = 16; 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ok = 0; 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey->initiator && !peerkey->stk_set) { 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion", 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->own_addr, peerkey->addr, 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->inonce, key->key_nonce, 92540b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt &peerkey->stk, peerkey->akmp, peerkey->cipher); 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->stk_set = 1; 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 92940b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt os_memcpy(mic, key->key_mic, mic_len); 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey->tstk_set) { 93140b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt os_memset(key->key_mic, 0, mic_len); 93240b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt wpa_eapol_key_mic(peerkey->tstk.kck, peerkey->tstk.kck_len, 93340b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt sm->key_mgmt, ver, buf, len, key->key_mic); 93440b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) { 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC " 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "when using TSTK - ignoring TSTK"); 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ok = 1; 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->tstk_set = 0; 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->stk_set = 1; 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&peerkey->stk, &peerkey->tstk, 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(peerkey->stk)); 94340b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt os_memset(&peerkey->tstk, 0, sizeof(peerkey->tstk)); 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ok && peerkey->stk_set) { 94840b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt os_memset(key->key_mic, 0, mic_len); 94940b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt wpa_eapol_key_mic(peerkey->stk.kck, peerkey->stk.kck_len, 95040b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt sm->key_mgmt, ver, buf, len, key->key_mic); 95140b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) { 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC " 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "- dropping packet"); 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ok = 1; 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ok) { 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Could not verify EAPOL-Key MIC " 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "- dropping packet"); 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->replay_counter, key->replay_counter, 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->replay_counter_set = 1; 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_stkstart - Send EAPOL-Key Request for STK handshake (STK M1) 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peer: MAC address of the peer STA 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, or -1 on failure 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Send an EAPOL-Key Request to the current authenticator to start STK 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * handshake with the peer. 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rlen, kde_len; 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *req; 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int key_info, ver; 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 bssid[ETH_ALEN], *rbuf, *pos, *count_pos; 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 count; 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_ie_hdr *hdr; 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey; 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data ie; 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->proto != WPA_PROTO_RSN || !sm->ptk_set || !sm->peerkey_enabled) 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->ap_rsn_ie && 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &ie) == 0 && 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(ie.capabilities & WPA_CAPABILITY_PEERKEY_ENABLED)) { 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Current AP does not support STK"); 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 100261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->pairwise_cipher != WPA_CIPHER_TKIP) 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_get_bssid(sm, bssid) < 0) { 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "Failed to read BSSID for EAPOL-Key " 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SMK M1"); 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: find existing entry and if found, use that instead of adding 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * a new one */ 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey = os_zalloc(sizeof(*peerkey)); 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey == NULL) 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->initiator = 1; 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->addr, peer, ETH_ALEN); 102040b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt peerkey->akmp = sm->key_mgmt; 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SMK M1: 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce, 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * MIC=MIC, DataKDs=(RSNIE_I, MAC_P KDE)) 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct rsn_ie_hdr *) peerkey->rsnie_i; 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->elem_id = WLAN_EID_RSN; 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(hdr->version, RSN_VERSION); 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (hdr + 1); 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Group Suite can be anything for SMK RSN IE; receiver will just 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ignore it. */ 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count_pos = pos; 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt count = rsn_cipher_put_suites(pos, sm->allowed_pairwise_cipher); 10394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt pos += count * RSN_SELECTOR_LEN; 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(count_pos, count); 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->len = (pos - peerkey->rsnie_i) - 2; 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_i_len = pos - peerkey->rsnie_i; 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake", 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_i, peerkey->rsnie_i_len); 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len = peerkey->rsnie_i_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN; 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(*req) + kde_len, &rlen, 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (void *) &req); 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) { 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_peerkey_free(sm, peerkey); 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req->type = EAPOL_KEY_TYPE_RSN; 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_SECURE | WPA_KEY_INFO_REQUEST | ver; 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(req->key_info, key_info); 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(req->key_length, 0); 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(req->replay_counter, sm->request_counter, 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(peerkey->inonce, WPA_NONCE_LEN)) { 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Failed to get random data for INonce"); 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rbuf); 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_peerkey_free(sm, peerkey); 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(req->key_nonce, peerkey->inonce, WPA_NONCE_LEN); 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: INonce for SMK handshake", 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req->key_nonce, WPA_NONCE_LEN); 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(req->key_data_length, (u16) kde_len); 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (req + 1); 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Initiator RSN IE */ 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len); 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Peer MAC address KDE */ 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN); 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Sending EAPOL-Key SMK M1 Request (peer " 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR ")", MAC2STR(peer)); 108740b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, bssid, 108840b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt ETH_P_EAPOL, rbuf, rlen, req->key_mic); 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->next = sm->peerkey; 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->peerkey = peerkey; 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * peerkey_deinit - Free PeerKey values 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid peerkey_deinit(struct wpa_sm *sm) 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *prev, *peerkey = sm->peerkey; 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (peerkey) { 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = peerkey; 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey = peerkey->next; 1107fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_supplicant_peerkey_free(sm, prev); 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->peerkey = NULL; 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey, 1114c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt struct wpa_eapol_key *key, u16 key_info, u16 ver, 1115c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt const u8 *key_data, size_t key_data_len) 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((key_info & (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) == 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) { 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3/4 STK 4-Way Handshake */ 1120c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt wpa_supplicant_process_stk_3_of_4(sm, peerkey, key, ver, 1121c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt key_data, key_data_len); 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_info & WPA_KEY_INFO_ACK) { 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1/4 STK 4-Way Handshake */ 1124c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt wpa_supplicant_process_stk_1_of_4(sm, peerkey, key, ver, 1125c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt key_data, key_data_len); 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_info & WPA_KEY_INFO_SECURE) { 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4/4 STK 4-Way Handshake */ 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_process_stk_4_of_4(sm, peerkey, key, ver); 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2/4 STK 4-Way Handshake */ 1131c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt wpa_supplicant_process_stk_2_of_4(sm, peerkey, key, ver, 1132c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt key_data, key_data_len); 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid peerkey_rx_eapol_smk(struct wpa_sm *sm, const u8 *src_addr, 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *key, size_t extra_len, 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info, u16 ver) 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_ERROR) { 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SMK Error */ 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_process_smk_error(sm, src_addr, key, extra_len); 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_info & WPA_KEY_INFO_ACK) { 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SMK M2 */ 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_process_smk_m2(sm, src_addr, key, extra_len, 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver); 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SMK M4 or M5 */ 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_process_smk_m45(sm, src_addr, key, extra_len, 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver); 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 1156