18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant - PeerKey for Direct Link Setup (DLS) 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2006-2008, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha1.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha256.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_i.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_ie.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "peerkey.h" 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * wpa_add_ie(u8 *pos, const u8 *ie, size_t ie_len) 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, ie, ie_len); 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos + ie_len; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len) 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = WLAN_EID_VENDOR_SPECIFIC; 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = RSN_SELECTOR_LEN + data_len; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, kde); 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, data, data_len); 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += data_len; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_smk_timeout(void *eloop_ctx, void *timeout_ctx) 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm = eloop_ctx; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey = timeout_ctx; 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: time out SMK and any STK that was generated using this SMK */ 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_peerkey_free(struct wpa_sm *sm, 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey) 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_supplicant_smk_timeout, sm, peerkey); 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(peerkey); 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_send_smk_error(struct wpa_sm *sm, const u8 *dst, 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *peer, 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 mui, u16 error_type, int ver) 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rlen; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *err; 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_error_kde error; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rbuf, *pos; 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t kde_len; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len = 2 + RSN_SELECTOR_LEN + sizeof(error); 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer) 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len += 2 + RSN_SELECTOR_LEN + ETH_ALEN; 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, sizeof(*err) + kde_len, &rlen, 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (void *) &err); 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err->type = EAPOL_KEY_TYPE_RSN; 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_SECURE | WPA_KEY_INFO_ERROR | 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_REQUEST; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(err->key_info, key_info); 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(err->key_length, 0); 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(err->replay_counter, sm->request_counter, 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(err->key_data_length, (u16) kde_len); 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (err + 1); 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer) { 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Peer MAC Address KDE */ 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN); 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Error KDE */ 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt error.mui = host_to_be16(mui); 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt error.error_type = host_to_be16(error_type); 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_add_kde(pos, RSN_KEY_DATA_ERROR, (u8 *) &error, sizeof(error)); 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer) { 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error (peer " 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " mui %d error_type %d)", 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peer), mui, error_type); 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error " 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(mui %d error_type %d)", mui, error_type); 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_send(sm, sm->ptk.kck, ver, dst, ETH_P_EAPOL, 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf, rlen, err->key_mic); 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_send_smk_m3(struct wpa_sm *sm, 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ver, struct wpa_peerkey *peerkey) 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rlen; 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *reply; 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rbuf, *pos; 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t kde_len; 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info; 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* KDEs: Peer RSN IE, Initiator MAC Address, Initiator Nonce */ 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len = peerkey->rsnie_p_len + 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + RSN_SELECTOR_LEN + ETH_ALEN + 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN; 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, sizeof(*reply) + kde_len, &rlen, 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (void *) &reply); 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reply->type = EAPOL_KEY_TYPE_RSN; 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_SECURE; 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_info, key_info); 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_length, 0); 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply->replay_counter, key->replay_counter, 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(reply->key_nonce, peerkey->pnonce, WPA_NONCE_LEN); 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(reply->key_data_length, (u16) kde_len); 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (reply + 1); 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Peer RSN IE */ 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len); 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Initiator MAC Address KDE */ 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peerkey->addr, ETH_ALEN); 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Initiator Nonce */ 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_add_kde(pos, RSN_KEY_DATA_NONCE, peerkey->inonce, WPA_NONCE_LEN); 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK M3"); 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_send(sm, sm->ptk.kck, ver, src_addr, ETH_P_EAPOL, 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf, rlen, reply->key_mic); 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_smk_m2( 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm, const unsigned char *src_addr, 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, size_t extra_len, int ver) 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey; 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data ie; 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int cipher; 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_ie_hdr *hdr; 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Received SMK M2"); 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) { 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: SMK handshake not allowed for " 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the current network"); 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) < 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) { 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M2"); 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie == NULL || kde.mac_addr == NULL || 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.mac_addr_len < ETH_ALEN) { 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No RSN IE or MAC address KDE in " 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SMK M2"); 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: SMK M2 - SMK initiator " MACSTR, 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(kde.mac_addr)); 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie_len > PEERKEY_MAX_IE_LEN) { 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Too long Initiator RSN IE in SMK " 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "M2"); 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) { 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Failed to parse RSN IE in SMK M2"); 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 220a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt cipher = wpa_pick_pairwise_cipher(ie.pairwise_cipher & 221a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt sm->allowed_pairwise_cipher, 0); 222a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (cipher < 0) { 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No acceptable cipher in SMK M2"); 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_send_smk_error(sm, src_addr, kde.mac_addr, 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt STK_MUI_SMK, STK_ERR_CPHR_NS, 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver); 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 229a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Using %s for PeerKey", 230a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_cipher_txt(cipher)); 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: find existing entry and if found, use that instead of adding 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * a new one; how to handle the case where both ends initiate at the 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * same time? */ 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey = os_zalloc(sizeof(*peerkey)); 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey == NULL) 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->addr, kde.mac_addr, ETH_ALEN); 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN); 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->rsnie_i, kde.rsn_ie, kde.rsn_ie_len); 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_i_len = kde.rsn_ie_len; 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->cipher = cipher; 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie.key_mgmt & (WPA_KEY_MGMT_IEEE8021X_SHA256 | 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_MGMT_PSK_SHA256)) 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->use_sha256 = 1; 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 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 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @use_sha256: Whether to use SHA256-based KDF 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, 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int use_sha256) 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 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (use_sha256) 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)); 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_send(sm, NULL, 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)); 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_send(sm, peerkey->stk.kck, ver, peerkey->addr, 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ETH_P_EAPOL, mbuf, mlen, msg->key_mic); 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_smk_m4(struct wpa_peerkey *peerkey, 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *kde) 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Received SMK M4 (Initiator " MACSTR ")", 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(kde->mac_addr)); 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(kde->smk + PMK_LEN, peerkey->pnonce, WPA_NONCE_LEN) != 0) 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: PNonce in SMK KDE does not " 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "match with the one used in SMK M3"); 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(kde->nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) { 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: INonce in SMK M4 did not " 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "match with the one received in SMK M2"); 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_smk_m5(struct wpa_sm *sm, 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ver, 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey, 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *kde) 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int cipher; 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data ie; 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Received SMK M5 (Peer " MACSTR ")", 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(kde->mac_addr)); 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde->rsn_ie == NULL || kde->rsn_ie_len > PEERKEY_MAX_IE_LEN || 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0) { 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No RSN IE in SMK M5"); 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: abort negotiation */ 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(key->key_nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) { 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Key Nonce in SMK M5 does " 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not match with INonce used in SMK M1"); 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(kde->smk + PMK_LEN, peerkey->inonce, WPA_NONCE_LEN) != 0) 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: INonce in SMK KDE does not " 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "match with the one used in SMK M1"); 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->rsnie_p, kde->rsn_ie, kde->rsn_ie_len); 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_p_len = kde->rsn_ie_len; 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->pnonce, kde->nonce, WPA_NONCE_LEN); 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 493a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt cipher = wpa_pick_pairwise_cipher(ie.pairwise_cipher & 494a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt sm->allowed_pairwise_cipher, 0); 495a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (cipher < 0) { 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: SMK Peer STA " MACSTR " selected " 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unacceptable cipher", MAC2STR(kde->mac_addr)); 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_send_smk_error(sm, src_addr, kde->mac_addr, 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt STK_MUI_SMK, STK_ERR_CPHR_NS, 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver); 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: abort negotiation */ 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 504a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Using %s for PeerKey", 505a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_cipher_txt(cipher)); 506a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt peerkey->cipher = cipher; 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_smk_m45( 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm, const unsigned char *src_addr, 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, size_t extra_len, int ver) 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey; 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime; 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) { 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for " 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the current network"); 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) < 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) { 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M4/M5"); 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN || 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN || 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.smk == NULL || kde.smk_len < PMK_LEN + WPA_NONCE_LEN || 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.lifetime == NULL || kde.lifetime_len < 4) { 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No MAC Address, Nonce, SMK, or " 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Lifetime KDE in SMK M4/M5"); 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) == 0 && 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(peerkey->initiator ? peerkey->inonce : 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->pnonce, 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_nonce, WPA_NONCE_LEN) == 0) 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey == NULL) { 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No matching SMK handshake found " 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for SMK M4/M5: peer " MACSTR, 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(kde.mac_addr)); 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey->initiator) { 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_process_smk_m5(sm, src_addr, key, ver, 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey, &kde) < 0) 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_process_smk_m4(peerkey, &kde) < 0) 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->smk, kde.smk, PMK_LEN); 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->smk_complete = 1; 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", peerkey->smk, PMK_LEN); 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = WPA_GET_BE32(kde.lifetime); 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: SMK lifetime %u seconds", lifetime); 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (lifetime > 1000000000) 570fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt lifetime = 1000000000; /* avoid overflowing eloop time */ 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->lifetime = lifetime; 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout, 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, peerkey); 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey->initiator) { 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_smkid(peerkey->smk, peerkey->pnonce, peerkey->addr, 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->inonce, sm->own_addr, peerkey->smkid, 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->use_sha256); 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_send_stk_1_of_4(sm, peerkey); 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_smkid(peerkey->smk, peerkey->pnonce, sm->own_addr, 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->inonce, peerkey->addr, peerkey->smkid, 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->use_sha256); 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: SMKID", peerkey->smkid, PMKID_LEN); 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_smk_error( 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm, const unsigned char *src_addr, 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, size_t extra_len) 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_error_kde error; 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 peer[ETH_ALEN]; 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 error_type; 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Received SMK Error"); 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) { 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for " 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the current network"); 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) < 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) { 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK Error"); 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.error == NULL || kde.error_len < sizeof(error)) { 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No Error KDE in SMK Error"); 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.mac_addr && kde.mac_addr_len >= ETH_ALEN) 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer, kde.mac_addr, ETH_ALEN); 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(peer, 0, ETH_ALEN); 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&error, kde.error, sizeof(error)); 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt error_type = be_to_host16(error.error_type); 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: SMK Error KDE received: MUI %d error_type %d peer " 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR, 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt be_to_host16(error.mui), error_type, 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peer)); 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.mac_addr && 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (error_type == STK_ERR_STA_NR || error_type == STK_ERR_STA_NRSN || 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt error_type == STK_ERR_CPHR_NS)) { 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey; 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) == 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey == NULL) { 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: No matching SMK handshake " 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "found for SMK Error"); 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: abort SMK/STK handshake and remove all related keys */ 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_stk_1_of_4(struct wpa_sm *sm, 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey, 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 656c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt u16 ver, const u8 *key_data, 657c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt size_t key_data_len) 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse ie; 660c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt size_t kde_buf_len; 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ptk *stk; 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 buf[8], *kde_buf, *pos; 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt be32 lifetime; 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: RX message 1 of STK 4-Way Handshake from " 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&ie, 0, sizeof(ie)); 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RSN: msg 1/4 should contain SMKID for the selected SMK */ 671c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", key_data, key_data_len); 672c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0 || 673c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt ie.pmkid == NULL) { 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: No SMKID in STK 1/4"); 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 677c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(ie.pmkid, peerkey->smkid, PMKID_LEN) != 0) { 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 1/4", 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie.pmkid, PMKID_LEN); 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(peerkey->pnonce, WPA_NONCE_LEN)) { 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: Failed to get random data for PNonce"); 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Renewed PNonce", 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->pnonce, WPA_NONCE_LEN); 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Calculate STK which will be stored as a temporary STK until it has 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * been verified when processing message 3/4. */ 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt stk = &peerkey->tstk; 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion", 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->own_addr, peerkey->addr, 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->pnonce, key->key_nonce, 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) stk, sizeof(*stk), 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->use_sha256); 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Supplicant: swap tx/rx Mic keys */ 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf, stk->u.auth.tx_mic_key, 8); 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(stk->u.auth.tx_mic_key, stk->u.auth.rx_mic_key, 8); 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(stk->u.auth.rx_mic_key, 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 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _key = (u8 *) peerkey->stk.tk1; 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); 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key_buf + 16, peerkey->stk.u.auth.rx_mic_key, 8); 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key_buf + 24, peerkey->stk.u.auth.tx_mic_key, 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) { 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the " 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "driver."); 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_stk_4_of_4(struct wpa_sm *sm, 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey, 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 ver) 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rsc[6]; 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: RX message 4 of STK 4-Way Handshake from " 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(rsc, 0, 6); 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1, 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsc, sizeof(rsc), (u8 *) peerkey->stk.tk1, 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->cipher == WPA_CIPHER_TKIP ? 32 : 16) < 0) { 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the " 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "driver."); 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * peerkey_verify_eapol_key_mic - Verify PeerKey MIC 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peerkey: Pointer to the PeerKey data for the peer 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key: Pointer to the EAPOL-Key frame header 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ver: Version bits from EAPOL-Key Key Info 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Pointer to the beginning of EAPOL-Key frame 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Length of the EAPOL-Key frame 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint peerkey_verify_eapol_key_mic(struct wpa_sm *sm, 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey, 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *key, u16 ver, 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mic[16]; 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ok = 0; 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey->initiator && !peerkey->stk_set) { 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion", 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->own_addr, peerkey->addr, 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->inonce, key->key_nonce, 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &peerkey->stk, sizeof(peerkey->stk), 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->use_sha256); 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->stk_set = 1; 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(mic, key->key_mic, 16); 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey->tstk_set) { 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(key->key_mic, 0, 16); 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_mic(peerkey->tstk.kck, ver, buf, len, 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_mic); 932c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(mic, key->key_mic, 16) != 0) { 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC " 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "when using TSTK - ignoring TSTK"); 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ok = 1; 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->tstk_set = 0; 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->stk_set = 1; 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&peerkey->stk, &peerkey->tstk, 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(peerkey->stk)); 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ok && peerkey->stk_set) { 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(key->key_mic, 0, 16); 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_mic(peerkey->stk.kck, ver, buf, len, 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_mic); 948c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(mic, key->key_mic, 16) != 0) { 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC " 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "- dropping packet"); 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ok = 1; 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ok) { 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Could not verify EAPOL-Key MIC " 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "- dropping packet"); 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->replay_counter, key->replay_counter, 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->replay_counter_set = 1; 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_stkstart - Send EAPOL-Key Request for STK handshake (STK M1) 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peer: MAC address of the peer STA 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, or -1 on failure 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Send an EAPOL-Key Request to the current authenticator to start STK 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * handshake with the peer. 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rlen, kde_len; 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *req; 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int key_info, ver; 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 bssid[ETH_ALEN], *rbuf, *pos, *count_pos; 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 count; 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_ie_hdr *hdr; 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey; 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data ie; 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->proto != WPA_PROTO_RSN || !sm->ptk_set || !sm->peerkey_enabled) 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->ap_rsn_ie && 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &ie) == 0 && 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(ie.capabilities & WPA_CAPABILITY_PEERKEY_ENABLED)) { 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Current AP does not support STK"); 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 99961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->pairwise_cipher != WPA_CIPHER_TKIP) 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_get_bssid(sm, bssid) < 0) { 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "Failed to read BSSID for EAPOL-Key " 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SMK M1"); 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: find existing entry and if found, use that instead of adding 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * a new one */ 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey = os_zalloc(sizeof(*peerkey)); 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey == NULL) 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->initiator = 1; 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->addr, peer, ETH_ALEN); 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_sha256(sm->key_mgmt)) 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->use_sha256 = 1; 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 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)); 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL, 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 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