18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd - PeerKey for Direct Link Setup (DLS) 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2006-2009, 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 "utils/includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/eloop.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha1.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha256.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_auth.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_auth_i.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_auth_ie.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_stsl_step(void *eloop_ctx, void *timeout_ctx) 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_authenticator *wpa_auth = eloop_ctx; 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_stsl_negotiation *neg = timeout_ctx; 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: ? */ 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_stsl_search { 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr; 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_stsl_select_sta(struct wpa_state_machine *sm, void *ctx) 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_stsl_search *search = ctx; 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(search->addr, sm->addr, ETH_ALEN) == 0) { 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt search->sm = sm; 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_smk_send_error(struct wpa_authenticator *wpa_auth, 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm, const u8 *peer, 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 mui, u16 error_type) 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 kde[2 + RSN_SELECTOR_LEN + ETH_ALEN + 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + RSN_SELECTOR_LEN + sizeof(struct rsn_error_kde)]; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_error_kde error; 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Sending SMK Error"); 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = kde; 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer) { 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN, 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0); 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt error.mui = host_to_be16(mui); 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt error.error_type = host_to_be16(error_type); 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_ERROR, 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &error, sizeof(error), NULL, 0); 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __wpa_send_eapol(wpa_auth, sm, 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC | 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_ERROR, 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, NULL, kde, pos - kde, 0, 0, 0); 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_smk_m1(struct wpa_authenticator *wpa_auth, 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm, struct wpa_eapol_key *key) 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_stsl_search search; 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *pos; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buf_len; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_parse_kde_ies((const u8 *) (key + 1), 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_BE16(key->key_data_length), &kde) < 0) { 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M1"); 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie == NULL || kde.mac_addr == NULL || 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.mac_addr_len < ETH_ALEN) { 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No RSN IE or MAC address KDE in " 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SMK M1"); 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Initiator = sm->addr; Peer = kde.mac_addr */ 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt search.addr = kde.mac_addr; 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt search.sm = NULL; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) == 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0 || search.sm == NULL) { 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: SMK handshake with " MACSTR 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " aborted - STA not associated anymore", 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(kde.mac_addr)); 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_smk_send_error(wpa_auth, sm, kde.mac_addr, STK_MUI_SMK, 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt STK_ERR_STA_NR); 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: wpa_stsl_remove(wpa_auth, neg); */ 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len = kde.rsn_ie_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN; 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_malloc(buf_len); 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Initiator RSN IE */ 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf, kde.rsn_ie, kde.rsn_ie_len); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf + kde.rsn_ie_len; 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Initiator MAC Address */ 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, sm->addr, ETH_ALEN, 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0); 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SMK M2: 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAPOL-Key(S=1, M=1, A=1, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce, 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * MIC=MIC, DataKDs=(RSNIE_I, MAC_I KDE) 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, search.sm->addr, LOGGER_DEBUG, 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Sending SMK M2"); 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __wpa_send_eapol(wpa_auth, search.sm, 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC | 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_ACK | WPA_KEY_INFO_SMK_MESSAGE, 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, key->key_nonce, buf, pos - buf, 0, 0, 0); 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_send_smk_m4(struct wpa_authenticator *wpa_auth, 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm, 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *key, 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *kde, 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *smk) 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *pos; 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buf_len; 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime; 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SMK M4: 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAPOL-Key(S=1, M=1, A=0, I=1, K=0, SM=1, KeyRSC=0, Nonce=PNonce, 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * MIC=MIC, DataKDs=(MAC_I KDE, INonce KDE, SMK KDE, 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Lifetime KDE) 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len = 2 + RSN_SELECTOR_LEN + ETH_ALEN + 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN + 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + RSN_SELECTOR_LEN + PMK_LEN + WPA_NONCE_LEN + 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + RSN_SELECTOR_LEN + sizeof(lifetime); 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf = os_malloc(buf_len); 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Initiator MAC Address */ 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, kde->mac_addr, ETH_ALEN, 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0); 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Initiator Nonce */ 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE, kde->nonce, WPA_NONCE_LEN, 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0); 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SMK with PNonce */ 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_SMK, smk, PMK_LEN, 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_nonce, WPA_NONCE_LEN); 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Lifetime */ 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = htonl(43200); /* dot11RSNAConfigSMKLifetime */ 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME, 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &lifetime, sizeof(lifetime), NULL, 0); 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Sending SMK M4"); 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __wpa_send_eapol(wpa_auth, sm, 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC | 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_INSTALL | WPA_KEY_INFO_SMK_MESSAGE, 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, key->key_nonce, buf, pos - buf, 0, 1, 0); 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_send_smk_m5(struct wpa_authenticator *wpa_auth, 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm, 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *key, 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *kde, 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *smk, const u8 *peer) 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *pos; 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buf_len; 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime; 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SMK M5: 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce, 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * MIC=MIC, DataKDs=(RSNIE_P, MAC_P KDE, PNonce, SMK KDE, 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Lifetime KDE)) 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len = kde->rsn_ie_len + 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + RSN_SELECTOR_LEN + ETH_ALEN + 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN + 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + RSN_SELECTOR_LEN + PMK_LEN + WPA_NONCE_LEN + 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + RSN_SELECTOR_LEN + sizeof(lifetime); 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf = os_malloc(buf_len); 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Peer RSN IE */ 2247d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt os_memcpy(pos, kde->rsn_ie, kde->rsn_ie_len); 2257d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt pos += kde->rsn_ie_len; 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Peer MAC Address */ 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN, NULL, 0); 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* PNonce */ 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE, key->key_nonce, 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_NONCE_LEN, NULL, 0); 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SMK and INonce */ 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_SMK, smk, PMK_LEN, 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde->nonce, WPA_NONCE_LEN); 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Lifetime */ 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = htonl(43200); /* dot11RSNAConfigSMKLifetime */ 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME, 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &lifetime, sizeof(lifetime), NULL, 0); 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Sending SMK M5"); 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __wpa_send_eapol(wpa_auth, sm, 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC | 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_SMK_MESSAGE, 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, kde->nonce, buf, pos - buf, 0, 1, 0); 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_smk_m3(struct wpa_authenticator *wpa_auth, 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm, struct wpa_eapol_key *key) 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_stsl_search search; 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 smk[32], buf[ETH_ALEN + 8 + 2 * WPA_NONCE_LEN], *pos; 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_parse_kde_ies((const u8 *) (key + 1), 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_BE16(key->key_data_length), &kde) < 0) { 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M3"); 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie == NULL || 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN || 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN) { 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No RSN IE, MAC address KDE, or " 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Nonce KDE in SMK M3"); 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Peer = sm->addr; Initiator = kde.mac_addr; 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Peer Nonce = key->key_nonce; Initiator Nonce = kde.nonce */ 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt search.addr = kde.mac_addr; 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt search.sm = NULL; 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) == 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0 || search.sm == NULL) { 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: SMK handshake with " MACSTR 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " aborted - STA not associated anymore", 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(kde.mac_addr)); 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_smk_send_error(wpa_auth, sm, kde.mac_addr, STK_MUI_SMK, 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt STK_ERR_STA_NR); 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: wpa_stsl_remove(wpa_auth, neg); */ 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(smk, PMK_LEN)) { 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Failed to generate SMK"); 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SMK = PRF-256(Random number, "SMK Derivation", 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AA || Time || INonce || PNonce) 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf, wpa_auth->addr, ETH_ALEN); 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf + ETH_ALEN; 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_get_ntp_timestamp(pos); 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 8; 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, kde.nonce, WPA_NONCE_LEN); 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += WPA_NONCE_LEN; 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, key->key_nonce, WPA_NONCE_LEN); 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf), 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt smk, PMK_LEN); 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_IEEE80211W */ 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha1_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf), 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt smk, PMK_LEN); 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", smk, PMK_LEN); 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_send_smk_m4(wpa_auth, sm, key, &kde, smk); 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_send_smk_m5(wpa_auth, search.sm, key, &kde, smk, sm->addr); 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Authenticator does not need SMK anymore and it is required to forget 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it. */ 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(smk, 0, sizeof(*smk)); 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_smk_error(struct wpa_authenticator *wpa_auth, 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm, struct wpa_eapol_key *key) 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_stsl_search search; 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_error_kde error; 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 mui, error_type; 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_parse_kde_ies((const u8 *) (key + 1), 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_BE16(key->key_data_length), &kde) < 0) { 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK Error"); 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN || 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.error == NULL || kde.error_len < sizeof(error)) { 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "RSN: No MAC address or Error KDE in " 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SMK Error"); 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt search.addr = kde.mac_addr; 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt search.sm = NULL; 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) == 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0 || search.sm == NULL) { 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Peer STA " MACSTR " not " 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "associated for SMK Error message from " MACSTR, 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(kde.mac_addr), MAC2STR(sm->addr)); 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&error, kde.error, sizeof(error)); 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mui = be_to_host16(error.mui); 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt error_type = be_to_host16(error.error_type); 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "STA reported SMK Error: Peer " MACSTR 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " MUI %d Error Type %d", 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(kde.mac_addr), mui, error_type); 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_smk_send_error(wpa_auth, search.sm, sm->addr, mui, error_type); 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_stsl_remove(struct wpa_authenticator *wpa_auth, 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_stsl_negotiation *neg) 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_stsl_negotiation *pos, *prev; 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL) 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_auth->stsl_negotiations; 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = NULL; 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos) { 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == neg) { 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prev) 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev->next = pos->next; 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->stsl_negotiations = pos->next; 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_stsl_step, wpa_auth, pos); 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(pos); 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = pos; 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = pos->next; 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 397