peerkey.c revision 4530cfd4d14a77c58e35393b91e40f8dd9d62697
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 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = ie.pairwise_cipher & sm->allowed_pairwise_cipher; 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cipher & WPA_CIPHER_CCMP) { 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Using CCMP for PeerKey"); 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = WPA_CIPHER_CCMP; 22461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else if (cipher & WPA_CIPHER_GCMP) { 22561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Using GCMP for PeerKey"); 22661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cipher = WPA_CIPHER_GCMP; 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (cipher & WPA_CIPHER_TKIP) { 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Using TKIP for PeerKey"); 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = WPA_CIPHER_TKIP; 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No acceptable cipher in SMK M2"); 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_send_smk_error(sm, src_addr, kde.mac_addr, 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt STK_MUI_SMK, STK_ERR_CPHR_NS, 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver); 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: find existing entry and if found, use that instead of adding 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * a new one; how to handle the case where both ends initiate at the 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * same time? */ 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey = os_zalloc(sizeof(*peerkey)); 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey == NULL) 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->addr, kde.mac_addr, ETH_ALEN); 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN); 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->rsnie_i, kde.rsn_ie, kde.rsn_ie_len); 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_i_len = kde.rsn_ie_len; 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->cipher = cipher; 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie.key_mgmt & (WPA_KEY_MGMT_IEEE8021X_SHA256 | 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_MGMT_PSK_SHA256)) 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->use_sha256 = 1; 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(peerkey->pnonce, WPA_NONCE_LEN)) { 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Failed to get random data for PNonce"); 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_peerkey_free(sm, peerkey); 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct rsn_ie_hdr *) peerkey->rsnie_p; 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->elem_id = WLAN_EID_RSN; 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(hdr->version, RSN_VERSION); 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (hdr + 1); 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Group Suite can be anything for SMK RSN IE; receiver will just 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ignore it. */ 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Include only the selected cipher in pairwise cipher suite */ 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, 1); 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 2734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN, cipher)); 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->len = (pos - peerkey->rsnie_p) - 2; 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_p_len = pos - peerkey->rsnie_p; 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake", 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_p, peerkey->rsnie_p_len); 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_send_smk_m3(sm, src_addr, key, ver, peerkey); 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->next = sm->peerkey; 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->peerkey = peerkey; 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rsn_smkid - Derive SMK identifier 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @smk: Station master key (32 bytes) 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pnonce: Peer Nonce 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mac_p: Peer MAC address 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @inonce: Initiator Nonce 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mac_i: Initiator MAC address 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @use_sha256: Whether to use SHA256-based KDF 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8.5.1.4 Station to station (STK) key hierarchy 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SMKID = HMAC-SHA1-128(SMK, "SMK Name" || PNonce || MAC_P || INonce || MAC_I) 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void rsn_smkid(const u8 *smk, const u8 *pnonce, const u8 *mac_p, 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *inonce, const u8 *mac_i, u8 *smkid, 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int use_sha256) 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *title = "SMK Name"; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[5]; 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const size_t len[5] = { 8, WPA_NONCE_LEN, ETH_ALEN, WPA_NONCE_LEN, 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ETH_ALEN }; 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned char hash[SHA256_MAC_LEN]; 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = (u8 *) title; 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = pnonce; 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = mac_p; 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[3] = inonce; 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[4] = mac_i; 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (use_sha256) 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha256_vector(smk, PMK_LEN, 5, addr, len, hash); 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha1_vector(smk, PMK_LEN, 5, addr, len, hash); 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(smkid, hash, PMKID_LEN); 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_send_stk_1_of_4(struct wpa_sm *sm, 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey) 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t mlen; 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *msg; 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *mbuf; 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t kde_len; 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info, ver; 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN; 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(*msg) + kde_len, &mlen, 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (void *) &msg); 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mbuf == NULL) 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg->type = EAPOL_KEY_TYPE_RSN; 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (peerkey->cipher != WPA_CIPHER_TKIP) 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK; 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(msg->key_info, key_info); 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (peerkey->cipher != WPA_CIPHER_TKIP) 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(msg->key_length, 16); 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(msg->key_length, 32); 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(msg->replay_counter, peerkey->replay_counter, 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN); 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(msg->key_data_length, kde_len); 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_add_kde((u8 *) (msg + 1), RSN_KEY_DATA_PMKID, 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->smkid, PMKID_LEN); 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(peerkey->inonce, WPA_NONCE_LEN)) { 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: Failed to get random data for INonce (STK)"); 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(mbuf); 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: INonce for STK 4-Way Handshake", 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->inonce, WPA_NONCE_LEN); 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN); 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 1/4 to " MACSTR, 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peerkey->addr)); 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_send(sm, NULL, ver, peerkey->addr, ETH_P_EAPOL, 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mbuf, mlen, NULL); 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_send_stk_3_of_4(struct wpa_sm *sm, 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey) 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t mlen; 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *msg; 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *mbuf, *pos; 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t kde_len; 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info, ver; 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt be32 lifetime; 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len = peerkey->rsnie_i_len + 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + RSN_SELECTOR_LEN + sizeof(lifetime); 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(*msg) + kde_len, &mlen, 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (void *) &msg); 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mbuf == NULL) 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg->type = EAPOL_KEY_TYPE_RSN; 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (peerkey->cipher != WPA_CIPHER_TKIP) 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK | 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE; 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(msg->key_info, key_info); 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 41561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (peerkey->cipher != WPA_CIPHER_TKIP) 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(msg->key_length, 16); 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(msg->key_length, 32); 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(msg->replay_counter, peerkey->replay_counter, 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN); 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(msg->key_data_length, kde_len); 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (msg + 1); 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len); 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = host_to_be32(peerkey->lifetime); 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME, 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &lifetime, sizeof(lifetime)); 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN); 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 3/4 to " MACSTR, 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peerkey->addr)); 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_send(sm, peerkey->stk.kck, ver, peerkey->addr, 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ETH_P_EAPOL, mbuf, mlen, msg->key_mic); 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_smk_m4(struct wpa_peerkey *peerkey, 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *kde) 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Received SMK M4 (Initiator " MACSTR ")", 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(kde->mac_addr)); 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(kde->smk + PMK_LEN, peerkey->pnonce, WPA_NONCE_LEN) != 0) 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: PNonce in SMK KDE does not " 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "match with the one used in SMK M3"); 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(kde->nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) { 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: INonce in SMK M4 did not " 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "match with the one received in SMK M2"); 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_smk_m5(struct wpa_sm *sm, 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ver, 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey, 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *kde) 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int cipher; 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data ie; 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Received SMK M5 (Peer " MACSTR ")", 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(kde->mac_addr)); 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde->rsn_ie == NULL || kde->rsn_ie_len > PEERKEY_MAX_IE_LEN || 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0) { 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No RSN IE in SMK M5"); 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: abort negotiation */ 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(key->key_nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) { 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Key Nonce in SMK M5 does " 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not match with INonce used in SMK M1"); 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(kde->smk + PMK_LEN, peerkey->inonce, WPA_NONCE_LEN) != 0) 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: INonce in SMK KDE does not " 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "match with the one used in SMK M1"); 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->rsnie_p, kde->rsn_ie, kde->rsn_ie_len); 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_p_len = kde->rsn_ie_len; 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->pnonce, kde->nonce, WPA_NONCE_LEN); 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = ie.pairwise_cipher & sm->allowed_pairwise_cipher; 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cipher & WPA_CIPHER_CCMP) { 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Using CCMP for PeerKey"); 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->cipher = WPA_CIPHER_CCMP; 50361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else if (cipher & WPA_CIPHER_GCMP) { 50461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Using GCMP for PeerKey"); 50561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt peerkey->cipher = WPA_CIPHER_GCMP; 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (cipher & WPA_CIPHER_TKIP) { 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Using TKIP for PeerKey"); 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->cipher = WPA_CIPHER_TKIP; 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: SMK Peer STA " MACSTR " selected " 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unacceptable cipher", MAC2STR(kde->mac_addr)); 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_send_smk_error(sm, src_addr, kde->mac_addr, 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt STK_MUI_SMK, STK_ERR_CPHR_NS, 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver); 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: abort negotiation */ 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_smk_m45( 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm, const unsigned char *src_addr, 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, size_t extra_len, int ver) 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey; 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime; 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct os_time now; 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) { 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for " 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the current network"); 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) < 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) { 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M4/M5"); 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN || 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN || 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.smk == NULL || kde.smk_len < PMK_LEN + WPA_NONCE_LEN || 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.lifetime == NULL || kde.lifetime_len < 4) { 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No MAC Address, Nonce, SMK, or " 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Lifetime KDE in SMK M4/M5"); 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) == 0 && 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(peerkey->initiator ? peerkey->inonce : 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->pnonce, 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_nonce, WPA_NONCE_LEN) == 0) 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey == NULL) { 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No matching SMK handshake found " 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for SMK M4/M5: peer " MACSTR, 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(kde.mac_addr)); 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey->initiator) { 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_process_smk_m5(sm, src_addr, key, ver, 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey, &kde) < 0) 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_process_smk_m4(peerkey, &kde) < 0) 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->smk, kde.smk, PMK_LEN); 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->smk_complete = 1; 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", peerkey->smk, PMK_LEN); 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = WPA_GET_BE32(kde.lifetime); 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: SMK lifetime %u seconds", lifetime); 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (lifetime > 1000000000) 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = 1000000000; /* avoid overflowing expiration time */ 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->lifetime = lifetime; 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_get_time(&now); 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->expiration = now.sec + lifetime; 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout, 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, peerkey); 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey->initiator) { 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_smkid(peerkey->smk, peerkey->pnonce, peerkey->addr, 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->inonce, sm->own_addr, peerkey->smkid, 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->use_sha256); 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_send_stk_1_of_4(sm, peerkey); 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_smkid(peerkey->smk, peerkey->pnonce, sm->own_addr, 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->inonce, peerkey->addr, peerkey->smkid, 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->use_sha256); 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: SMKID", peerkey->smkid, PMKID_LEN); 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_smk_error( 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm, const unsigned char *src_addr, 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, size_t extra_len) 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_error_kde error; 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 peer[ETH_ALEN]; 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 error_type; 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Received SMK Error"); 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) { 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for " 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the current network"); 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) < 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) { 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK Error"); 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.error == NULL || kde.error_len < sizeof(error)) { 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No Error KDE in SMK Error"); 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.mac_addr && kde.mac_addr_len >= ETH_ALEN) 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer, kde.mac_addr, ETH_ALEN); 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(peer, 0, ETH_ALEN); 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&error, kde.error, sizeof(error)); 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt error_type = be_to_host16(error.error_type); 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: SMK Error KDE received: MUI %d error_type %d peer " 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR, 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt be_to_host16(error.mui), error_type, 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peer)); 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.mac_addr && 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (error_type == STK_ERR_STA_NR || error_type == STK_ERR_STA_NRSN || 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt error_type == STK_ERR_CPHR_NS)) { 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey; 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) == 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey == NULL) { 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: No matching SMK handshake " 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "found for SMK Error"); 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: abort SMK/STK handshake and remove all related keys */ 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_stk_1_of_4(struct wpa_sm *sm, 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey, 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 ver) 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse ie; 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *kde; 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len, kde_buf_len; 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ptk *stk; 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 buf[8], *kde_buf, *pos; 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt be32 lifetime; 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: RX message 1 of STK 4-Way Handshake from " 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&ie, 0, sizeof(ie)); 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RSN: msg 1/4 should contain SMKID for the selected SMK */ 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde = (const u8 *) (key + 1); 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = WPA_GET_BE16(key->key_data_length); 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", kde, len); 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_parse_ies(kde, len, &ie) < 0 || ie.pmkid == NULL) { 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: No SMKID in STK 1/4"); 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(ie.pmkid, peerkey->smkid, PMKID_LEN) != 0) { 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 1/4", 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie.pmkid, PMKID_LEN); 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(peerkey->pnonce, WPA_NONCE_LEN)) { 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: Failed to get random data for PNonce"); 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Renewed PNonce", 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->pnonce, WPA_NONCE_LEN); 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Calculate STK which will be stored as a temporary STK until it has 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * been verified when processing message 3/4. */ 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt stk = &peerkey->tstk; 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion", 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->own_addr, peerkey->addr, 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->pnonce, key->key_nonce, 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) stk, sizeof(*stk), 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->use_sha256); 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Supplicant: swap tx/rx Mic keys */ 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf, stk->u.auth.tx_mic_key, 8); 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(stk->u.auth.tx_mic_key, stk->u.auth.rx_mic_key, 8); 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(stk->u.auth.rx_mic_key, buf, 8); 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->tstk_set = 1; 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_buf_len = peerkey->rsnie_p_len + 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + RSN_SELECTOR_LEN + sizeof(lifetime) + 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + RSN_SELECTOR_LEN + PMKID_LEN; 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_buf = os_malloc(kde_buf_len); 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde_buf == NULL) 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = kde_buf; 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len); 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = host_to_be32(peerkey->lifetime); 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME, 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &lifetime, sizeof(lifetime)); 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_add_kde(pos, RSN_KEY_DATA_PMKID, peerkey->smkid, PMKID_LEN); 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_send_2_of_4(sm, peerkey->addr, key, ver, 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->pnonce, kde_buf, kde_buf_len, 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt stk)) { 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(kde_buf); 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(kde_buf); 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN); 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_update_smk_lifetime(struct wpa_sm *sm, 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey, 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *kde) 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime; 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct os_time now; 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde->lifetime == NULL || kde->lifetime_len < sizeof(lifetime)) 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = WPA_GET_BE32(kde->lifetime); 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (lifetime >= peerkey->lifetime) { 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Peer used SMK lifetime %u seconds " 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "which is larger than or equal to own value %u " 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "seconds - ignored", lifetime, peerkey->lifetime); 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Peer used shorter SMK lifetime %u seconds " 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(own was %u seconds) - updated", 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime, peerkey->lifetime); 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->lifetime = lifetime; 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_get_time(&now); 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->expiration = now.sec + lifetime; 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_supplicant_smk_timeout, sm, peerkey); 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout, 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, peerkey); 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_stk_2_of_4(struct wpa_sm *sm, 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey, 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 ver) 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *keydata; 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: RX message 2 of STK 4-Way Handshake from " 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&kde, 0, sizeof(kde)); 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RSN: msg 2/4 should contain SMKID for the selected SMK and RSN IE 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * from the peer. It may also include Lifetime KDE. */ 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keydata = (const u8 *) (key + 1); 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = WPA_GET_BE16(key->key_data_length); 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: msg 2/4 key data", keydata, len); 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_parse_ies(keydata, len, &kde) < 0 || 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.pmkid == NULL || kde.rsn_ie == NULL) { 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: No SMKID or RSN IE in STK 2/4"); 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(kde.pmkid, peerkey->smkid, PMKID_LEN) != 0) { 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 2/4", 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.pmkid, PMKID_LEN); 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie_len != peerkey->rsnie_p_len || 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(kde.rsn_ie, peerkey->rsnie_p, kde.rsn_ie_len) != 0) { 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Peer RSN IE in SMK and STK " 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "handshakes did not match"); 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Peer RSN IE in SMK handshake", 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_p, peerkey->rsnie_p_len); 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Peer RSN IE in STK handshake", 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.rsn_ie, kde.rsn_ie_len); 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_update_smk_lifetime(sm, peerkey, &kde); 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_send_stk_3_of_4(sm, peerkey); 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->pnonce, key->key_nonce, WPA_NONCE_LEN); 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_stk_3_of_4(struct wpa_sm *sm, 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey, 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 ver) 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *keydata; 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len, key_len; 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *_key; 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 key_buf[32], rsc[6]; 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: RX message 3 of STK 4-Way Handshake from " 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&kde, 0, sizeof(kde)); 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RSN: msg 3/4 should contain Initiator RSN IE. It may also include 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Lifetime KDE. */ 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keydata = (const u8 *) (key + 1); 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = WPA_GET_BE16(key->key_data_length); 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: msg 3/4 key data", keydata, len); 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_parse_ies(keydata, len, &kde) < 0) { 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Failed to parse key data in " 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "STK 3/4"); 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie_len != peerkey->rsnie_i_len || 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(kde.rsn_ie, peerkey->rsnie_i, kde.rsn_ie_len) != 0) { 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Initiator RSN IE in SMK and STK " 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "handshakes did not match"); 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Initiator RSN IE in SMK " 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "handshake", 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_i, peerkey->rsnie_i_len); 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Initiator RSN IE in STK " 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "handshake", 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.rsn_ie, kde.rsn_ie_len); 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN) != 0) { 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: INonce from message 1 of STK " 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "4-Way Handshake differs from 3 of STK 4-Way " 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Handshake - drop packet (src=" MACSTR ")", 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peerkey->addr)); 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_update_smk_lifetime(sm, peerkey, &kde); 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_send_4_of_4(sm, peerkey->addr, key, ver, 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_BE16(key->key_info), 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0, &peerkey->stk)) 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _key = (u8 *) peerkey->stk.tk1; 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey->cipher == WPA_CIPHER_TKIP) { 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Swap Tx/Rx keys for Michael MIC */ 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key_buf, _key, 16); 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key_buf + 16, peerkey->stk.u.auth.rx_mic_key, 8); 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key_buf + 24, peerkey->stk.u.auth.tx_mic_key, 8); 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _key = key_buf; 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_len = 32; 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_len = 16; 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(rsc, 0, 6); 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1, 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsc, sizeof(rsc), _key, key_len) < 0) { 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the " 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "driver."); 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_stk_4_of_4(struct wpa_sm *sm, 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey, 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key, 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 ver) 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rsc[6]; 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: RX message 4 of STK 4-Way Handshake from " 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(rsc, 0, 6); 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1, 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsc, sizeof(rsc), (u8 *) peerkey->stk.tk1, 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->cipher == WPA_CIPHER_TKIP ? 32 : 16) < 0) { 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the " 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "driver."); 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * peerkey_verify_eapol_key_mic - Verify PeerKey MIC 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peerkey: Pointer to the PeerKey data for the peer 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key: Pointer to the EAPOL-Key frame header 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ver: Version bits from EAPOL-Key Key Info 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Pointer to the beginning of EAPOL-Key frame 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Length of the EAPOL-Key frame 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint peerkey_verify_eapol_key_mic(struct wpa_sm *sm, 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey, 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *key, u16 ver, 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mic[16]; 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ok = 0; 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey->initiator && !peerkey->stk_set) { 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion", 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->own_addr, peerkey->addr, 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->inonce, key->key_nonce, 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &peerkey->stk, sizeof(peerkey->stk), 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->use_sha256); 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->stk_set = 1; 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(mic, key->key_mic, 16); 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey->tstk_set) { 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(key->key_mic, 0, 16); 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_mic(peerkey->tstk.kck, ver, buf, len, 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_mic); 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(mic, key->key_mic, 16) != 0) { 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC " 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "when using TSTK - ignoring TSTK"); 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ok = 1; 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->tstk_set = 0; 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->stk_set = 1; 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&peerkey->stk, &peerkey->tstk, 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(peerkey->stk)); 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ok && peerkey->stk_set) { 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(key->key_mic, 0, 16); 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_mic(peerkey->stk.kck, ver, buf, len, 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_mic); 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(mic, key->key_mic, 16) != 0) { 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC " 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "- dropping packet"); 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ok = 1; 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ok) { 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Could not verify EAPOL-Key MIC " 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "- dropping packet"); 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->replay_counter, key->replay_counter, 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->replay_counter_set = 1; 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_stkstart - Send EAPOL-Key Request for STK handshake (STK M1) 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peer: MAC address of the peer STA 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, or -1 on failure 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Send an EAPOL-Key Request to the current authenticator to start STK 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * handshake with the peer. 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rlen, kde_len; 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *req; 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int key_info, ver; 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 bssid[ETH_ALEN], *rbuf, *pos, *count_pos; 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 count; 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_ie_hdr *hdr; 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *peerkey; 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data ie; 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->proto != WPA_PROTO_RSN || !sm->ptk_set || !sm->peerkey_enabled) 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->ap_rsn_ie && 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &ie) == 0 && 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(ie.capabilities & WPA_CAPABILITY_PEERKEY_ENABLED)) { 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Current AP does not support STK"); 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 102261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->pairwise_cipher != WPA_CIPHER_TKIP) 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_get_bssid(sm, bssid) < 0) { 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "Failed to read BSSID for EAPOL-Key " 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SMK M1"); 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: find existing entry and if found, use that instead of adding 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * a new one */ 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey = os_zalloc(sizeof(*peerkey)); 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peerkey == NULL) 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->initiator = 1; 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peerkey->addr, peer, ETH_ALEN); 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_sha256(sm->key_mgmt)) 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->use_sha256 = 1; 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SMK M1: 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce, 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * MIC=MIC, DataKDs=(RSNIE_I, MAC_P KDE)) 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct rsn_ie_hdr *) peerkey->rsnie_i; 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->elem_id = WLAN_EID_RSN; 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(hdr->version, RSN_VERSION); 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (hdr + 1); 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Group Suite can be anything for SMK RSN IE; receiver will just 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ignore it. */ 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count_pos = pos; 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt count = rsn_cipher_put_suites(pos, sm->allowed_pairwise_cipher); 10624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt pos += count * RSN_SELECTOR_LEN; 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(count_pos, count); 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->len = (pos - peerkey->rsnie_i) - 2; 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_i_len = pos - peerkey->rsnie_i; 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake", 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->rsnie_i, peerkey->rsnie_i_len); 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len = peerkey->rsnie_i_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN; 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(*req) + kde_len, &rlen, 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (void *) &req); 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) { 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_peerkey_free(sm, peerkey); 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req->type = EAPOL_KEY_TYPE_RSN; 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_SECURE | WPA_KEY_INFO_REQUEST | ver; 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(req->key_info, key_info); 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(req->key_length, 0); 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(req->replay_counter, sm->request_counter, 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(peerkey->inonce, WPA_NONCE_LEN)) { 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA: Failed to get random data for INonce"); 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rbuf); 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_peerkey_free(sm, peerkey); 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(req->key_nonce, peerkey->inonce, WPA_NONCE_LEN); 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: INonce for SMK handshake", 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req->key_nonce, WPA_NONCE_LEN); 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(req->key_data_length, (u16) kde_len); 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (req + 1); 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Initiator RSN IE */ 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len); 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Peer MAC address KDE */ 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN); 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Sending EAPOL-Key SMK M1 Request (peer " 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR ")", MAC2STR(peer)); 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL, 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf, rlen, req->key_mic); 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey->next = sm->peerkey; 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->peerkey = peerkey; 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * peerkey_deinit - Free PeerKey values 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid peerkey_deinit(struct wpa_sm *sm) 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_peerkey *prev, *peerkey = sm->peerkey; 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (peerkey) { 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = peerkey; 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peerkey = peerkey->next; 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(prev); 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->peerkey = NULL; 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey, 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *key, u16 key_info, u16 ver) 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((key_info & (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) == 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) { 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3/4 STK 4-Way Handshake */ 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_process_stk_3_of_4(sm, peerkey, key, ver); 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_info & WPA_KEY_INFO_ACK) { 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1/4 STK 4-Way Handshake */ 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_process_stk_1_of_4(sm, peerkey, key, ver); 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_info & WPA_KEY_INFO_SECURE) { 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4/4 STK 4-Way Handshake */ 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_process_stk_4_of_4(sm, peerkey, key, ver); 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2/4 STK 4-Way Handshake */ 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_process_stk_2_of_4(sm, peerkey, key, ver); 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid peerkey_rx_eapol_smk(struct wpa_sm *sm, const u8 *src_addr, 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *key, size_t extra_len, 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info, u16 ver) 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_ERROR) { 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SMK Error */ 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_process_smk_error(sm, src_addr, key, extra_len); 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_info & WPA_KEY_INFO_ACK) { 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SMK M2 */ 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_process_smk_m2(sm, src_addr, key, extra_len, 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver); 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SMK M4 or M5 */ 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_process_smk_m45(sm, src_addr, key, extra_len, 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver); 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 1175