wpa_auth.c revision f7e0a9905988e62e4f70fed8b795722abeab719b
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 21f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * IEEE 802.11 RSN / WPA Authenticator 31f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Copyright (c) 2004-2011, 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 "utils/state_machine.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/aes_wrap.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/crypto.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha1.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha256.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eapol_auth/eapol_auth_sm.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap_config.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ieee802_11.h" 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_auth.h" 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "pmksa_cache_auth.h" 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_auth_i.h" 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_auth_ie.h" 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STATE_MACHINE_DATA struct wpa_state_machine 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STATE_MACHINE_DEBUG_PREFIX "WPA" 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STATE_MACHINE_ADDR sm->addr 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx); 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_sm_step(struct wpa_state_machine *sm); 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_verify_key_mic(struct wpa_ptk *PTK, u8 *data, size_t data_len); 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx); 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_group_sm_step(struct wpa_authenticator *wpa_auth, 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group); 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_request_new_ptk(struct wpa_state_machine *sm); 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_gtk_update(struct wpa_authenticator *wpa_auth, 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group); 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth, 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group); 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u32 dot11RSNAConfigGroupUpdateCount = 4; 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u32 dot11RSNAConfigPairwiseUpdateCount = 4; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u32 eapol_key_timeout_first = 100; /* ms */ 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u32 eapol_key_timeout_subseq = 1000; /* ms */ 491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic const u32 eapol_key_timeout_first_group = 500; /* ms */ 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* TODO: make these configurable */ 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const int dot11RSNAConfigPMKLifetime = 43200; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const int dot11RSNAConfigPMKReauthThreshold = 70; 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const int dot11RSNAConfigSATimeout = 60; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic inline int wpa_auth_mic_failure_report( 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_authenticator *wpa_auth, const u8 *addr) 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.mic_failure_report) 61d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return wpa_auth->cb.mic_failure_report(wpa_auth->cb.ctx, addr); 62d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return 0; 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline void wpa_auth_set_eapol(struct wpa_authenticator *wpa_auth, 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, wpa_eapol_variable var, 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int value) 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.set_eapol) 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->cb.set_eapol(wpa_auth->cb.ctx, addr, var, value); 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline int wpa_auth_get_eapol(struct wpa_authenticator *wpa_auth, 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, wpa_eapol_variable var) 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.get_eapol == NULL) 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->cb.get_eapol(wpa_auth->cb.ctx, addr, var); 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth, 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, const u8 *prev_psk) 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.get_psk == NULL) 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->cb.get_psk(wpa_auth->cb.ctx, addr, prev_psk); 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline int wpa_auth_get_msk(struct wpa_authenticator *wpa_auth, 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, u8 *msk, size_t *len) 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.get_msk == NULL) 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->cb.get_msk(wpa_auth->cb.ctx, addr, msk, len); 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int vlan_id, 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wpa_alg alg, const u8 *addr, int idx, 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key, size_t key_len) 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.set_key == NULL) 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->cb.set_key(wpa_auth->cb.ctx, vlan_id, alg, addr, idx, 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key, key_len); 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth, 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, int idx, u8 *seq) 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.get_seqnum == NULL) 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->cb.get_seqnum(wpa_auth->cb.ctx, addr, idx, seq); 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline int 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr, 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *data, size_t data_len, int encrypt) 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.send_eapol == NULL) 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->cb.send_eapol(wpa_auth->cb.ctx, addr, data, data_len, 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encrypt); 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth, 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int (*cb)(struct wpa_state_machine *sm, void *ctx), 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *cb_ctx) 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.for_each_sta == NULL) 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->cb.for_each_sta(wpa_auth->cb.ctx, cb, cb_ctx); 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth, 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int (*cb)(struct wpa_authenticator *a, void *ctx), 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *cb_ctx) 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.for_each_auth == NULL) 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->cb.for_each_auth(wpa_auth->cb.ctx, cb, cb_ctx); 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr, 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt logger_level level, const char *txt) 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.logger == NULL) 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->cb.logger(wpa_auth->cb.ctx, addr, level, txt); 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr, 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt logger_level level, const char *fmt, ...) 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *format; 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int maxlen; 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt va_list ap; 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.logger == NULL) 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt maxlen = os_strlen(fmt) + 100; 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt format = os_malloc(maxlen); 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!format) 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt va_start(ap, fmt); 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vsnprintf(format, maxlen, fmt, ap); 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt va_end(ap); 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, addr, level, format); 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(format); 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth, 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr) 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.disconnect == NULL) 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR, MAC2STR(addr)); 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->cb.disconnect(wpa_auth->cb.ctx, addr, 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_REASON_PREV_AUTH_NOT_VALID); 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_use_aes_cmac(struct wpa_state_machine *sm) 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 1; 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_sha256(sm->wpa_key_mgmt)) 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 1; 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx) 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_authenticator *wpa_auth = eloop_ctx; 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(wpa_auth->group->GMK, WPA_GMK_LEN)) { 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Failed to get random data for WPA " 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "initialization."); 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "GMK rekeyd"); 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "GMK", 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->group->GMK, WPA_GMK_LEN); 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->conf.wpa_gmk_rekey) { 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0, 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_rekey_gmk, wpa_auth, NULL); 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx) 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_authenticator *wpa_auth = eloop_ctx; 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group; 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "rekeying GTK"); 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (group = wpa_auth->group; group; group = group->next) { 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTKReKey = TRUE; 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt do { 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->changed = FALSE; 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_sm_step(wpa_auth, group); 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } while (group->changed); 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->conf.wpa_group_rekey) { 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, wpa_rekey_gtk, wpa_auth, NULL); 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_rekey_ptk(void *eloop_ctx, void *timeout_ctx) 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_authenticator *wpa_auth = eloop_ctx; 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm = timeout_ctx; 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "rekeying PTK"); 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_request_new_ptk(sm); 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_step(sm); 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_auth_pmksa_clear_cb(struct wpa_state_machine *sm, void *ctx) 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pmksa == ctx) 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmksa = NULL; 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_auth_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry, 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *ctx) 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_authenticator *wpa_auth = ctx; 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_for_each_sta(wpa_auth, wpa_auth_pmksa_clear_cb, entry); 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_group_init_gmk_and_counter(struct wpa_authenticator *wpa_auth, 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group) 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 285a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt u8 buf[ETH_ALEN + 8 + sizeof(unsigned long)]; 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rkey[32]; 287a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt unsigned long ptr; 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(group->GMK, WPA_GMK_LEN) < 0) 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "GMK", group->GMK, WPA_GMK_LEN); 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Counter = PRF-256(Random number, "Init Counter", 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Local MAC Address || Time) 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf, wpa_auth->addr, ETH_ALEN); 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_get_ntp_timestamp(buf + ETH_ALEN); 299a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt ptr = (unsigned long) group; 300a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt os_memcpy(buf + ETH_ALEN + 8, &ptr, sizeof(ptr)); 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(rkey, sizeof(rkey)) < 0) 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sha1_prf(rkey, sizeof(rkey), "Init Counter", buf, sizeof(buf), 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->Counter, WPA_NONCE_LEN) < 0) 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "Key Counter", 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->Counter, WPA_NONCE_LEN); 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth, 3151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int vlan_id, int delay_init) 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group; 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = os_zalloc(sizeof(struct wpa_group)); 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group == NULL) 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTKAuthenticator = TRUE; 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->vlan_id = vlan_id; 3254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group); 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_pool_ready() != 1) { 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPA: Not enough entropy in random pool " 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for secure operations - update keys later when " 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the first station connects"); 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Set initial GMK/Counter value here. The actual values that will be 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * used in negotiations will be set once the first station tries to 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * connect. This allows more time for collecting additional randomness 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * on embedded devices. 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0) { 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Failed to get random data for WPA " 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "initialization."); 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(group); 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GInit = TRUE; 3471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (delay_init) { 3481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Delay group state machine start " 3491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "until Beacon frames have been configured"); 3501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Initialization is completed in wpa_init_keys(). */ 3511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else { 3521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_group_sm_step(wpa_auth, group); 3531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt group->GInit = FALSE; 3541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_group_sm_step(wpa_auth, group); 3551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return group; 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_init - Initialize WPA authenticator 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: Authenticator address 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @conf: Configuration for WPA authenticator 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cb: Callback functions for WPA authenticator 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to WPA authenticator data or %NULL on failure 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_authenticator * wpa_init(const u8 *addr, 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_auth_config *conf, 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_auth_callbacks *cb) 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_authenticator *wpa_auth; 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth = os_zalloc(sizeof(struct wpa_authenticator)); 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL) 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wpa_auth->addr, addr, ETH_ALEN); 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&wpa_auth->conf, conf, sizeof(*conf)); 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&wpa_auth->cb, cb, sizeof(*cb)); 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_gen_wpa_ie(wpa_auth)) { 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not generate WPA IE."); 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth); 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_auth->group = wpa_group_init(wpa_auth, 0, 1); 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->group == NULL) { 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth->wpa_ie); 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth); 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->pmksa = pmksa_cache_auth_init(wpa_auth_pmksa_free_cb, 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth); 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->pmksa == NULL) { 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "PMKSA cache initialization failed."); 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth->wpa_ie); 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth); 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->ft_pmk_cache = wpa_ft_pmk_cache_init(); 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->ft_pmk_cache == NULL) { 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "FT PMK cache initialization failed."); 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth->wpa_ie); 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_cache_auth_deinit(wpa_auth->pmksa); 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth); 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->conf.wpa_gmk_rekey) { 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0, 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_rekey_gmk, wpa_auth, NULL); 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->conf.wpa_group_rekey) { 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, 0, 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_rekey_gtk, wpa_auth, NULL); 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth; 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint wpa_init_keys(struct wpa_authenticator *wpa_auth) 4291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 4301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_group *group = wpa_auth->group; 4311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Start group state machine to set initial " 4331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "keys"); 4341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_group_sm_step(wpa_auth, group); 4351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt group->GInit = FALSE; 4361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_group_sm_step(wpa_auth, group); 4371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 4381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 4391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_deinit - Deinitialize WPA authenticator 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_auth: Pointer to WPA authenticator data from wpa_init() 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_deinit(struct wpa_authenticator *wpa_auth) 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group, *prev; 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_rekey_gmk, wpa_auth, NULL); 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL); 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (wpa_auth->stsl_negotiations) 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_stsl_remove(wpa_auth, wpa_auth->stsl_negotiations); 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_cache_auth_deinit(wpa_auth->pmksa); 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ft_pmk_cache_deinit(wpa_auth->ft_pmk_cache); 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->ft_pmk_cache = NULL; 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth->wpa_ie); 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = wpa_auth->group; 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (group) { 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = group; 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = group->next; 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(prev); 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth); 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_reconfig - Update WPA authenticator configuration 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_auth: Pointer to WPA authenticator data from wpa_init() 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @conf: Configuration for WPA authenticator 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_reconfig(struct wpa_authenticator *wpa_auth, 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_auth_config *conf) 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group; 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL) 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&wpa_auth->conf, conf, sizeof(*conf)); 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_gen_wpa_ie(wpa_auth)) { 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not generate WPA IE."); 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Reinitialize GTK to make sure it is suitable for the new 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * configuration. 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = wpa_auth->group; 5004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group); 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GInit = TRUE; 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_sm_step(wpa_auth, group); 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GInit = FALSE; 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_sm_step(wpa_auth, group); 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_state_machine * 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr) 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm = os_zalloc(sizeof(struct wpa_state_machine)); 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->addr, addr, ETH_ALEN); 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_auth = wpa_auth; 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group = wpa_auth->group; 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm; 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm) 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->ft_completed) { 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FT authentication already completed - do not " 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "start 4-way handshake"); 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->started) { 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&sm->key_replay, 0, sizeof(sm->key_replay)); 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ReAuthenticationRequest = TRUE; 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_sm_step(sm); 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "start authentication"); 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->started = 1; 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->Init = TRUE; 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_step(sm) == 1) 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; /* should not really happen */ 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->Init = FALSE; 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->AuthenticationRequest = TRUE; 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_sm_step(sm); 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_auth_sta_no_wpa(struct wpa_state_machine *sm) 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* WPA/RSN was not used - clear WPA state. This is needed if the STA 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * reassociates back to the same AP while the previous entry for the 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * STA has not yet been removed. */ 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_key_mgmt = 0; 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_free_sta_sm(struct wpa_state_machine *sm) 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->GUpdateStationKeys) { 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group->GKeyDoneStations--; 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GUpdateStationKeys = FALSE; 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->assoc_resp_ftie); 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->last_rx_eapol_key); 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->wpa_ie); 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm); 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_auth_sta_deinit(struct wpa_state_machine *sm) 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) { 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "strict rekeying - force GTK rekey since STA " 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "is leaving"); 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_rekey_gtk, sm->wpa_auth, NULL); 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(0, 500000, wpa_rekey_gtk, sm->wpa_auth, 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL); 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm); 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pending_1_of_4_timeout = 0; 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_sm_call_step, sm, NULL); 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->in_step_loop) { 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Must not free state machine while wpa_sm_step() is running. 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Freeing will be completed in the end of wpa_sm_step(). */ 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Registering pending STA state " 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "machine deinit for " MACSTR, MAC2STR(sm->addr)); 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pending_deinit = 1; 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_free_sta_sm(sm); 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_request_new_ptk(struct wpa_state_machine *sm) 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PTKRequest = TRUE; 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PTK_valid = 0; 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 627c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic int wpa_replay_counter_valid(struct wpa_key_replay_counter *ctr, 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *replay_counter) 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { 632c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (!ctr[i].valid) 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 634c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (os_memcmp(replay_counter, ctr[i].counter, 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN) == 0) 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 642c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic void wpa_replay_counter_mark_invalid(struct wpa_key_replay_counter *ctr, 643c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt const u8 *replay_counter) 644c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{ 645c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt int i; 646c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { 647c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (ctr[i].valid && 648c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt (replay_counter == NULL || 649c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt os_memcmp(replay_counter, ctr[i].counter, 650c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt WPA_REPLAY_COUNTER_LEN) == 0)) 651c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt ctr[i].valid = FALSE; 652c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 653c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt} 654c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 655c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth, 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm, 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *kde) 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data ie; 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_mdie *mdie; 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0 || 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie.num_pmkid != 1 || ie.pmkid == NULL) { 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "FT: No PMKR1Name in " 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FT 4-way handshake message 2/4"); 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->sup_pmk_r1_name, ie.pmkid, PMKID_LEN); 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Supplicant", 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->sup_pmk_r1_name, PMKID_LEN); 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!kde->mdie || !kde->ftie) { 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "FT: No %s in FT 4-way handshake " 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message 2/4", kde->mdie ? "FTIE" : "MDIE"); 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mdie = (struct rsn_mdie *) (kde->mdie + 2); 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde->mdie[1] < sizeof(struct rsn_mdie) || 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(wpa_auth->conf.mobility_domain, mdie->mobility_domain, 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MOBILITY_DOMAIN_ID_LEN) != 0) { 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "FT: MDIE mismatch"); 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->assoc_resp_ftie && 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (kde->ftie[1] != sm->assoc_resp_ftie[1] || 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(kde->ftie, sm->assoc_resp_ftie, 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + sm->assoc_resp_ftie[1]) != 0)) { 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "FT: FTIE mismatch"); 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 2/4", 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde->ftie, kde->ftie_len); 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)AssocResp", 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->assoc_resp_ftie, 2 + sm->assoc_resp_ftie[1]); 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 706d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic int wpa_receive_error_report(struct wpa_authenticator *wpa_auth, 707d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt struct wpa_state_machine *sm, int group) 7081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 7091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Supplicant reported a Michael MIC error */ 7101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, 7111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "received EAPOL-Key Error Request " 7121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "(STA detected Michael MIC failure (group=%d))", 7131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt group); 7141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (group && wpa_auth->conf.wpa_group != WPA_CIPHER_TKIP) { 7161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 7171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "ignore Michael MIC failure report since " 7181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "group cipher is not TKIP"); 7191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else if (!group && sm->pairwise != WPA_CIPHER_TKIP) { 7201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 7211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "ignore Michael MIC failure report since " 7221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "pairwise cipher is not TKIP"); 7231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else { 724d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (wpa_auth_mic_failure_report(wpa_auth, sm->addr) > 0) 725d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return 1; /* STA entry was removed */ 7261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt sm->dot11RSNAStatsTKIPRemoteMICFailures++; 7271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_auth->dot11RSNAStatsTKIPRemoteMICFailures++; 7281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 7291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 7311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Error report is not a request for a new key handshake, but since 7321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Authenticator may do it, let's change the keys now anyway. 7331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 7341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_request_new_ptk(sm); 735d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return 0; 7361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 7371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_receive(struct wpa_authenticator *wpa_auth, 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm, 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *data, size_t data_len) 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee802_1x_hdr *hdr; 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *key; 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info, key_data_length; 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST, 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SMK_M1, SMK_M3, SMK_ERROR } msg; 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *msgtxt; 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ft; 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *eapol_key_ie; 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t eapol_key_ie_len; 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data_len < sizeof(*hdr) + sizeof(*key)) 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct ieee802_1x_hdr *) data; 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = (struct wpa_eapol_key *) (hdr + 1); 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = WPA_GET_BE16(key->key_info); 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_data_length = WPA_GET_BE16(key->key_data_length); 7641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR 7651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " key_info=0x%x type=%u key_data_length=%u", 7661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(sm->addr), key_info, key->type, key_data_length); 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_data_length > data_len - sizeof(*hdr) - sizeof(*key)) { 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPA: Invalid EAPOL-Key frame - " 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "key_data overflow (%d > %lu)", 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_data_length, 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) (data_len - sizeof(*hdr) - 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(*key))); 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA2) { 777c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (key->type == EAPOL_KEY_TYPE_WPA) { 778c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 779c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * Some deployed station implementations seem to send 780c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * msg 4/4 with incorrect type value in WPA2 mode. 781c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 782c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_DEBUG, "Workaround: Allow EAPOL-Key " 783c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "with unexpected WPA type in RSN mode"); 784c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } else if (key->type != EAPOL_KEY_TYPE_RSN) { 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with " 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unexpected type %d in RSN mode", 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->type); 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key->type != EAPOL_KEY_TYPE_WPA) { 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with " 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unexpected type %d in WPA mode", 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->type); 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Received Key Nonce", key->key_nonce, 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_NONCE_LEN); 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Received Replay Counter", 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->replay_counter, WPA_REPLAY_COUNTER_LEN); 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: verify that the EAPOL-Key frame was encrypted if pairwise keys 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * are set */ 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((key_info & (WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_REQUEST)) == 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_REQUEST)) { 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_ERROR) { 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = SMK_ERROR; 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msgtxt = "SMK Error"; 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = SMK_M1; 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msgtxt = "SMK M1"; 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) { 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = SMK_M3; 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msgtxt = "SMK M3"; 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_info & WPA_KEY_INFO_REQUEST) { 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = REQUEST; 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msgtxt = "Request"; 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (!(key_info & WPA_KEY_INFO_KEY_TYPE)) { 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = GROUP_2; 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msgtxt = "2/2 Group"; 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_data_length == 0) { 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = PAIRWISE_4; 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msgtxt = "4/4 Pairwise"; 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = PAIRWISE_2; 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msgtxt = "2/4 Pairwise"; 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: key_info type validation for PeerKey */ 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == REQUEST || msg == PAIRWISE_2 || msg == PAIRWISE_4 || 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg == GROUP_2) { 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 ver = key_info & WPA_KEY_INFO_TYPE_MASK; 83761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->pairwise == WPA_CIPHER_CCMP || 83861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sm->pairwise == WPA_CIPHER_GCMP) { 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_use_aes_cmac(sm) && 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt LOGGER_WARNING, 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "advertised support for " 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "AES-128-CMAC, but did not " 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "use it"); 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_use_aes_cmac(sm) && 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt LOGGER_WARNING, 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "did not use HMAC-SHA1-AES " 85461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "with CCMP/GCMP"); 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_REQUEST) { 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->req_replay_counter_used && 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(key->replay_counter, sm->req_replay_counter, 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN) <= 0) { 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING, 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key request with " 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "replayed counter"); 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(key_info & WPA_KEY_INFO_REQUEST) && 872c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt !wpa_replay_counter_valid(sm->key_replay, key->replay_counter)) { 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 874c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 875c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (msg == PAIRWISE_2 && 876c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_replay_counter_valid(sm->prev_key_replay, 877c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt key->replay_counter) && 878c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING && 879c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt os_memcmp(sm->SNonce, key->key_nonce, WPA_NONCE_LEN) != 0) 880c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt { 881c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 882c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * Some supplicant implementations (e.g., Windows XP 883c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * WZC) update SNonce for each EAPOL-Key 2/4. This 884c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * breaks the workaround on accepting any of the 885c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * pending requests, so allow the SNonce to be updated 886c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * even if we have already sent out EAPOL-Key 3/4. 887c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 888c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, 889c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "Process SNonce update from STA " 890c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "based on retransmitted EAPOL-Key " 891c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "1/4"); 892c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sm->update_snonce = 1; 893c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_replay_counter_mark_invalid(sm->prev_key_replay, 894c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt key->replay_counter); 895c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt goto continue_processing; 896c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 897c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 898c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (msg == PAIRWISE_2 && 899c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_replay_counter_valid(sm->prev_key_replay, 900c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt key->replay_counter) && 901c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING) { 902c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, 903c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "ignore retransmitted EAPOL-Key %s - " 904c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "SNonce did not change", msgtxt); 905c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } else { 906c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, 907c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "received EAPOL-Key %s with " 908c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "unexpected replay counter", msgtxt); 909c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->key_replay[i].valid) 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "pending replay counter", 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->key_replay[i].counter, 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "received replay counter", 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->replay_counter, WPA_REPLAY_COUNTER_LEN); 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 922c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtcontinue_processing: 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (msg) { 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PAIRWISE_2: 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_ptk_state != WPA_PTK_PTKSTART && 926c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sm->wpa_ptk_state != WPA_PTK_PTKCALCNEGOTIATING && 927c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt (!sm->update_snonce || 928c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING)) { 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key msg 2/4 in " 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "invalid state (%d) - dropped", 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ptk_state); 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt random_add_randomness(key->key_nonce, WPA_NONCE_LEN); 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->group->reject_4way_hs_for_entropy) { 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The system did not have enough entropy to generate 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * strong random numbers. Reject the first 4-way 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * handshake(s) and collect some entropy based on the 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * information from it. Once enough entropy is 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * available, the next atempt will trigger GMK/Key 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Counter update and the station will be allowed to 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * continue. 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Reject 4-way handshake to " 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "collect more entropy for random number " 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "generation"); 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt random_mark_pool_ready(); 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sta_disconnect(wpa_auth, sm->addr); 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_parse_kde_ies((u8 *) (key + 1), key_data_length, 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &kde) < 0) { 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key msg 2/4 with " 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "invalid Key Data contents"); 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie) { 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_key_ie = kde.rsn_ie; 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_key_ie_len = kde.rsn_ie_len; 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_key_ie = kde.wpa_ie; 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_key_ie_len = kde.wpa_ie_len; 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ft = sm->wpa == WPA_VERSION_WPA2 && 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_key_mgmt_ft(sm->wpa_key_mgmt); 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_ie == NULL || 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_compare_rsn_ie(ft, 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ie, sm->wpa_ie_len, 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_key_ie, eapol_key_ie_len)) { 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA IE from (Re)AssocReq did not " 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "match with msg 2/4"); 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_ie) { 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA IE in AssocReq", 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ie, sm->wpa_ie_len); 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA IE in msg 2/4", 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_key_ie, eapol_key_ie_len); 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* MLME-DEAUTHENTICATE.request */ 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sta_disconnect(wpa_auth, sm->addr); 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) { 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sta_disconnect(wpa_auth, sm->addr); 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PAIRWISE_4: 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING || 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !sm->PTK_valid) { 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key msg 4/4 in " 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "invalid state (%d) - dropped", 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ptk_state); 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case GROUP_2: 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_ptk_group_state != WPA_PTK_GROUP_REKEYNEGOTIATING 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt || !sm->PTK_valid) { 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key msg 2/2 in " 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "invalid state (%d) - dropped", 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ptk_group_state); 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SMK_M1: 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SMK_M3: 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SMK_ERROR: 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_auth->conf.peerkey) { 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: SMK M1/M3/Error, but " 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PeerKey use disabled - ignoring message"); 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->PTK_valid) { 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key msg SMK in " 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "invalid state - dropped"); 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_PEERKEY */ 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SMK_M1: 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SMK_M3: 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SMK_ERROR: 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; /* STSL disabled - ignore SMK messages */ 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case REQUEST: 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key frame (%s)", msgtxt); 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_ACK) { 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received invalid EAPOL-Key: Key Ack set"); 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(key_info & WPA_KEY_INFO_MIC)) { 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received invalid EAPOL-Key: Key MIC not set"); 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->MICVerified = FALSE; 1055c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (sm->PTK_valid && !sm->update_snonce) { 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_verify_key_mic(&sm->PTK, data, data_len)) { 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key with invalid MIC"); 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->MICVerified = TRUE; 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm); 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pending_1_of_4_timeout = 0; 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_REQUEST) { 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->MICVerified) { 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->req_replay_counter_used = 1; 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->req_replay_counter, key->replay_counter, 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key request with " 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "invalid MIC"); 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO: should decrypt key data field if encryption was used; 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * even though MAC address KDE is not normally encrypted, 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * supplicant is allowed to encrypt it. 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == SMK_ERROR) { 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_smk_error(wpa_auth, sm, key); 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_info & WPA_KEY_INFO_ERROR) { 1089d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (wpa_receive_error_report( 1090d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_auth, sm, 1091d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt !(key_info & WPA_KEY_INFO_KEY_TYPE)) > 0) 1092d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return; /* STA entry was removed */ 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_info & WPA_KEY_INFO_KEY_TYPE) { 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key Request for new " 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "4-Way Handshake"); 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_request_new_ptk(sm); 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (msg == SMK_M1) { 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_smk_m1(wpa_auth, sm, key); 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_data_length > 0 && 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_parse_kde_ies((const u8 *) (key + 1), 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_data_length, &kde) == 0 && 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.mac_addr) { 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key Request for GTK " 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "rekeying"); 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL); 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_rekey_gtk(wpa_auth, NULL); 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1114c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* Do not allow the same key replay counter to be reused. */ 1115c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_replay_counter_mark_invalid(sm->key_replay, 1116c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt key->replay_counter); 1117c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 1118c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (msg == PAIRWISE_2) { 1119c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 1120c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * Maintain a copy of the pending EAPOL-Key frames in 1121c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * case the EAPOL-Key frame was retransmitted. This is 1122c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * needed to allow EAPOL-Key msg 2/4 reply to another 1123c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * pending msg 1/4 to update the SNonce to work around 1124c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * unexpected supplicant behavior. 1125c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 1126c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt os_memcpy(sm->prev_key_replay, sm->key_replay, 1127c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sizeof(sm->key_replay)); 1128c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } else { 1129c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt os_memset(sm->prev_key_replay, 0, 1130c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sizeof(sm->prev_key_replay)); 1131c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 1132c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 1133c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 1134c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * Make sure old valid counters are not accepted anymore and 1135c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * do not get copied again. 1136c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 1137c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_replay_counter_mark_invalid(sm->key_replay, NULL); 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == SMK_M3) { 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_smk_m3(wpa_auth, sm, key); 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->last_rx_eapol_key); 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->last_rx_eapol_key = os_malloc(data_len); 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->last_rx_eapol_key == NULL) 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->last_rx_eapol_key, data, data_len); 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->last_rx_eapol_key_len = data_len; 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt sm->rx_eapol_key_secure = !!(key_info & WPA_KEY_INFO_SECURE); 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->EAPOLKeyReceived = TRUE; 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE); 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST); 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN); 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_step(sm); 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr, 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *gnonce, u8 *gtk, size_t gtk_len) 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 data[ETH_ALEN + WPA_NONCE_LEN + 8 + 16]; 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* GTK = PRF-X(GMK, "Group key expansion", 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AA || GNonce || Time || random data) 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The example described in the IEEE 802.11 standard uses only AA and 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * GNonce as inputs here. Add some more entropy since this derivation 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * is done only at the Authenticator and as such, does not need to be 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * exactly same. 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data, addr, ETH_ALEN); 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN); 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = data + ETH_ALEN + WPA_NONCE_LEN; 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_get_ntp_timestamp(pos); 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 8; 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(pos, 16) < 0) 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), gtk, gtk_len); 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_IEEE80211W */ 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sha1_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), gtk, gtk_len) 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt < 0) 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx) 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_authenticator *wpa_auth = eloop_ctx; 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm = timeout_ctx; 12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pending_1_of_4_timeout = 0; 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "EAPOL-Key timeout"); 12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutEvt = TRUE; 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_step(sm); 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid __wpa_send_eapol(struct wpa_authenticator *wpa_auth, 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm, int key_info, 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *key_rsc, const u8 *nonce, 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *kde, size_t kde_len, 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int keyidx, int encr, int force_version) 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee802_1x_hdr *hdr; 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *key; 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int alg; 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int key_data_len, pad_len = 0; 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *pos; 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int version, pairwise; 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = sizeof(struct ieee802_1x_hdr) + sizeof(struct wpa_eapol_key); 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (force_version) 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt version = force_version; 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (wpa_use_aes_cmac(sm)) 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt version = WPA_KEY_INFO_TYPE_AES_128_CMAC; 123061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt else if (sm->pairwise != WPA_CIPHER_TKIP) 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt version = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 123551b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt pairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE); 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Send EAPOL(version=%d secure=%d mic=%d " 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ack=%d install=%d pairwise=%d kde_len=%lu keyidx=%d " 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "encr=%d)", 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt version, 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (key_info & WPA_KEY_INFO_SECURE) ? 1 : 0, 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (key_info & WPA_KEY_INFO_MIC) ? 1 : 0, 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (key_info & WPA_KEY_INFO_ACK) ? 1 : 0, 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (key_info & WPA_KEY_INFO_INSTALL) ? 1 : 0, 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pairwise, (unsigned long) kde_len, keyidx, encr); 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_data_len = kde_len; 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) { 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad_len = key_data_len % 8; 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pad_len) 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad_len = 8 - pad_len; 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_data_len += pad_len + 8; 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += key_data_len; 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = os_zalloc(len); 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr == NULL) 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->version = wpa_auth->conf.eapol_version; 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->type = IEEE802_1X_TYPE_EAPOL_KEY; 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->length = host_to_be16(len - sizeof(*hdr)); 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = (struct wpa_eapol_key *) (hdr + 1); 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->type = sm->wpa == WPA_VERSION_WPA2 ? 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info |= version; 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (encr && sm->wpa == WPA_VERSION_WPA2) 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info |= WPA_KEY_INFO_ENCR_KEY_DATA; 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa != WPA_VERSION_WPA2) 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info |= keyidx << WPA_KEY_INFO_KEY_INDEX_SHIFT; 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(key->key_info, key_info); 12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt alg = pairwise ? sm->pairwise : wpa_auth->conf.wpa_group; 12774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt WPA_PUT_BE16(key->key_length, wpa_cipher_key_len(alg)); 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_SMK_MESSAGE) 12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(key->key_length, 0); 12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: STSL: what to use as key_replay_counter? */ 12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = RSNA_MAX_EAPOL_RETRIES - 1; i > 0; i--) { 12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->key_replay[i].valid = sm->key_replay[i - 1].valid; 12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->key_replay[i].counter, 12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->key_replay[i - 1].counter, 12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(sm->key_replay[0].counter, WPA_REPLAY_COUNTER_LEN); 12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key->replay_counter, sm->key_replay[0].counter, 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->key_replay[0].valid = TRUE; 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nonce) 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key->key_nonce, nonce, WPA_NONCE_LEN); 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_rsc) 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key->key_rsc, key_rsc, WPA_KEY_RSC_LEN); 12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde && !encr) { 13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key + 1, kde, kde_len); 13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(key->key_data_length, kde_len); 13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (encr && kde) { 13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_zalloc(key_data_len); 13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(hdr); 13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, kde, kde_len); 13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += kde_len; 13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pad_len) 13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 0xdd; 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data", 13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf, key_data_len); 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || 13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt version == WPA_KEY_INFO_TYPE_AES_128_CMAC) { 13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (aes_wrap(sm->PTK.kek, (key_data_len - 8) / 8, buf, 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) (key + 1))) { 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(hdr); 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(key->key_data_length, key_data_len); 13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ek[32]; 13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key->key_iv, 13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group->Counter + WPA_NONCE_LEN - 16, 16); 13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(sm->group->Counter, WPA_NONCE_LEN); 13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ek, key->key_iv, 16); 13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ek + 16, sm->PTK.kek, 16); 13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key + 1, buf, key_data_len); 13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rc4_skip(ek, 32, 256, (u8 *) (key + 1), key_data_len); 13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(key->key_data_length, key_data_len); 13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_MIC) { 13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->PTK_valid) { 13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, 13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PTK not valid when sending EAPOL-Key " 13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "frame"); 13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(hdr); 13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_mic(sm->PTK.kck, version, (u8 *) hdr, len, 13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_mic); 135051b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt#ifdef CONFIG_TESTING_OPTIONS 135151b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt if (!pairwise && 135251b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt wpa_auth->conf.corrupt_gtk_rekey_mic_probability > 0.0d && 135351b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt drand48() < 135451b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt wpa_auth->conf.corrupt_gtk_rekey_mic_probability) { 135551b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 135651b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt "Corrupting group EAPOL-Key Key MIC"); 135751b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt key->key_mic[0]++; 135851b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt } 135951b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt#endif /* CONFIG_TESTING_OPTIONS */ 13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, 13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1); 13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_send_eapol(wpa_auth, sm->addr, (u8 *) hdr, len, 13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pairwise_set); 13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(hdr); 13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_send_eapol(struct wpa_authenticator *wpa_auth, 13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm, int key_info, 13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *key_rsc, const u8 *nonce, 13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *kde, size_t kde_len, 13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int keyidx, int encr) 13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int timeout_ms; 13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE; 13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ctr; 13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len, 13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keyidx, encr, 0); 13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctr = pairwise ? sm->TimeoutCtr : sm->GTimeoutCtr; 13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ctr == 1 && wpa_auth->conf.tx_status) 13881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt timeout_ms = pairwise ? eapol_key_timeout_first : 13891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eapol_key_timeout_first_group; 13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeout_ms = eapol_key_timeout_subseq; 13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pairwise && ctr == 1 && !(key_info & WPA_KEY_INFO_MIC)) 13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pending_1_of_4_timeout = 1; 13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Use EAPOL-Key timeout of %u ms (retry " 13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "counter %d)", timeout_ms, ctr); 13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000, 13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_send_eapol_timeout, wpa_auth, sm); 13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_verify_key_mic(struct wpa_ptk *PTK, u8 *data, size_t data_len) 14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee802_1x_hdr *hdr; 14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *key; 14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info; 14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mic[16]; 14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data_len < sizeof(*hdr) + sizeof(*key)) 14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct ieee802_1x_hdr *) data; 14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = (struct wpa_eapol_key *) (hdr + 1); 14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = WPA_GET_BE16(key->key_info); 14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(mic, key->key_mic, 16); 14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(key->key_mic, 0, 16); 14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_eapol_key_mic(PTK->kck, key_info & WPA_KEY_INFO_TYPE_MASK, 14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data, data_len, key->key_mic) || 14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(mic, key->key_mic, 16) != 0) 14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key->key_mic, mic, 16); 14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_remove_ptk(struct wpa_state_machine *sm) 14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PTK_valid = FALSE; 14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&sm->PTK, 0, sizeof(sm->PTK)); 14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, NULL, 0); 14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pairwise_set = FALSE; 14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); 14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event) 14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int remove_ptk = 1; 14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "event %d notification", event); 14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (event) { 14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_AUTH: 14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_ASSOC: 14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_DEAUTH: 14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_DISASSOC: 14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->DeauthenticationRequest = TRUE; 14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_REAUTH: 14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_REAUTH_EAPOL: 14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->started) { 14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * When using WPS, we may end up here if the STA 14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * manages to re-associate without the previous STA 14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * entry getting removed. Consequently, we need to make 14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * sure that the WPA state machines gets initialized 14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * properly at this point. 14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA state machine had not been " 14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "started - initialize now"); 14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->started = 1; 14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->Init = TRUE; 14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_step(sm) == 1) 14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; /* should not really happen */ 14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->Init = FALSE; 14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->AuthenticationRequest = TRUE; 14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->GUpdateStationKeys) { 14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Reauthentication cancels the pending group key 14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * update for this STA. 14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group->GKeyDoneStations--; 14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GUpdateStationKeys = FALSE; 14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PtkGroupInit = TRUE; 14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ReAuthenticationRequest = TRUE; 14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_ASSOC_FT: 14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "FT: Retry PTK configuration " 14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "after association"); 14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ft_install_ptk(sm); 14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Using FT protocol, not WPA auth state machine */ 14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ft_completed = 1; 14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_IEEE80211R */ 14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ft_completed = 0; 15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->mgmt_frame_prot && event == WPA_AUTH) 15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt remove_ptk = 0; 15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (remove_ptk) { 15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PTK_valid = FALSE; 15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&sm->PTK, 0, sizeof(sm->PTK)); 15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (event != WPA_REAUTH_EAPOL) 15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_remove_ptk(sm); 15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_sm_step(sm); 15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, INITIALIZE) 15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, INITIALIZE, wpa_ptk); 15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->Init) { 15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Init flag is not cleared here, so avoid busy 15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * loop by claiming nothing changed. */ 15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->changed = FALSE; 15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->keycount = 0; 15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->GUpdateStationKeys) 15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group->GKeyDoneStations--; 15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GUpdateStationKeys = FALSE; 15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA) 15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PInitAKeys = FALSE; 15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (1 /* Unicast cipher supported AND (ESS OR ((IBSS or WDS) and 15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Local AA > Remote AA)) */) { 15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->Pair = TRUE; 15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 0); 15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_remove_ptk(sm); 15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 0); 15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutCtr = 0; 15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { 15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, 15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_EAPOL_authorized, 0); 15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, DISCONNECT) 15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, DISCONNECT, wpa_ptk); 15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->Disconnect = FALSE; 15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sta_disconnect(sm->wpa_auth, sm->addr); 15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, DISCONNECTED) 15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, DISCONNECTED, wpa_ptk); 15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->DeauthenticationRequest = FALSE; 15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, AUTHENTICATION) 15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, AUTHENTICATION, wpa_ptk); 15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&sm->PTK, 0, sizeof(sm->PTK)); 15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PTK_valid = FALSE; 15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portControl_Auto, 15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1); 15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 1); 15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->AuthenticationRequest = FALSE; 15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1577c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic void wpa_group_ensure_init(struct wpa_authenticator *wpa_auth, 1578c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct wpa_group *group) 15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1580c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (group->first_sta_seen) 1581c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return; 15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * System has run bit further than at the time hostapd was started 15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * potentially very early during boot up. This provides better chances 15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * of collecting more randomness on embedded systems. Re-initialize the 15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * GMK and Counter here to improve their strength if there was not 15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * enough entropy available immediately after system startup. 15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Re-initialize GMK/Counter on first " 15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "station"); 15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_pool_ready() != 1) { 15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPA: Not enough entropy in random pool " 15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "to proceed - reject first 4-way handshake"); 15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->reject_4way_hs_for_entropy = TRUE; 1595c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } else { 1596c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt group->first_sta_seen = TRUE; 1597c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt group->reject_4way_hs_for_entropy = FALSE; 15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1599c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_init_gmk_and_counter(wpa_auth, group); 16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_gtk_update(wpa_auth, group); 16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_config_group_keys(wpa_auth, group); 16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, AUTHENTICATION2) 16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, AUTHENTICATION2, wpa_ptk); 16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1610c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_group_ensure_init(sm->wpa_auth, sm->group); 1611444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt sm->ReAuthenticationRequest = FALSE; 16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 161304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* 161404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * Definition of ANonce selection in IEEE Std 802.11i-2004 is somewhat 161504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * ambiguous. The Authenticator state machine uses a counter that is 161604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * incremented by one for each 4-way handshake. However, the security 161704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * analysis of 4-way handshake points out that unpredictable nonces 161804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * help in preventing precomputation attacks. Instead of the state 161904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * machine definition, use an unpredictable nonce value here to provide 162004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * stronger protection against potential precomputation attacks. 162104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt */ 162204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) { 162304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_ERROR, "WPA: Failed to get random data for " 162404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "ANonce."); 1625444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt sm->Disconnect = TRUE; 162604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 162704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Assign ANonce", sm->ANonce, 16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_NONCE_LEN); 16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* IEEE 802.11i does not clear TimeoutCtr here, but this is more 16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * logical place than INITIALIZE since AUTHENTICATION2 can be 16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * re-entered on ReAuthenticationRequest without going through 16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * INITIALIZE. */ 16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutCtr = 0; 16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, INITPMK) 16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 msk[2 * PMK_LEN]; 16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len = 2 * PMK_LEN; 16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, INITPMK, wpa_ptk); 16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->xxkey_len = 0; 16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pmksa) { 16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: PMK from PMKSA cache"); 16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->PMK, sm->pmksa->pmk, PMK_LEN); 16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (wpa_auth_get_msk(sm->wpa_auth, sm->addr, msk, &len) == 0) { 16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: PMK from EAPOL state machine " 16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(len=%lu)", (unsigned long) len); 16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->PMK, msk, PMK_LEN); 16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len >= 2 * PMK_LEN) { 16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->xxkey, msk + PMK_LEN, PMK_LEN); 16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->xxkey_len = PMK_LEN; 16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Could not get PMK"); 16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->req_replay_counter_used = 0; 16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* IEEE 802.11i does not set keyRun to FALSE, but not doing this 16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * will break reauthentication since EAPOL state machines may not be 16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * get into AUTHENTICATING state that clears keyRun before WPA state 16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * machine enters AUTHENTICATION2 state and goes immediately to INITPMK 16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * state and takes PMK from the previously used AAA Key. This will 16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eventually fail in 4-Way Handshake because Supplicant uses PMK 16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * derived from the new AAA Key. Setting keyRun = FALSE here seems to 16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * be good workaround for this issue. */ 16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun, 0); 16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, INITPSK) 16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *psk; 16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk); 16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, NULL); 16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (psk) { 16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->PMK, psk, PMK_LEN); 16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->xxkey, psk, PMK_LEN); 16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->xxkey_len = PMK_LEN; 16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->req_replay_counter_used = 0; 16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, PTKSTART) 16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 buf[2 + RSN_SELECTOR_LEN + PMKID_LEN], *pmkid = NULL; 16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t pmkid_len = 0; 16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, PTKSTART, wpa_ptk); 16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PTKRequest = FALSE; 17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutEvt = FALSE; 17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutCtr++; 17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->TimeoutCtr > (int) dot11RSNAConfigPairwiseUpdateCount) { 17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No point in sending the EAPOL-Key - we will disconnect 17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * immediately following this. */ 17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "sending 1/4 msg of 4-Way Handshake"); 17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO: Could add PMKID even with WPA2-PSK, but only if there is only 17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * one possible PSK for this STA. 17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA2 && 17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt)) { 17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmkid = buf; 17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN; 17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmkid[0] = WLAN_EID_VENDOR_SPECIFIC; 17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN; 17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(&pmkid[2], RSN_KEY_DATA_PMKID); 17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pmksa) 17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN], 17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmksa->pmkid, PMKID_LEN); 17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Calculate PMKID since no PMKSA cache entry was 17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * available with pre-calculated PMKID. 17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_pmkid(sm->PMK, PMK_LEN, sm->wpa_auth->addr, 17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->addr, &pmkid[2 + RSN_SELECTOR_LEN], 17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_key_mgmt_sha256(sm->wpa_key_mgmt)); 17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_send_eapol(sm->wpa_auth, sm, 17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL, 17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ANonce, pmkid, pmkid_len, 0, 0); 17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *pmk, 17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ptk *ptk) 17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 174461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t ptk_len = sm->pairwise != WPA_CIPHER_TKIP ? 48 : 64; 17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) 17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth_derive_ptk_ft(sm, pmk, ptk, ptk_len); 17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_pmk_to_ptk(pmk, PMK_LEN, "Pairwise key expansion", 17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_auth->addr, sm->addr, sm->ANonce, sm->SNonce, 17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) ptk, ptk_len, 17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_key_mgmt_sha256(sm->wpa_key_mgmt)); 17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, PTKCALCNEGOTIATING) 17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ptk PTK; 17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ok = 0; 17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pmk = NULL; 17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk); 17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->EAPOLKeyReceived = FALSE; 1767c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sm->update_snonce = FALSE; 17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* WPA with IEEE 802.1X: use the derived PMK from EAP 17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA-PSK: iterate through possible PSKs and select the one matching 17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the packet */ 17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (;;) { 17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { 17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, pmk); 17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmk == NULL) 17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmk = sm->PMK; 17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_derive_ptk(sm, pmk, &PTK); 17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_verify_key_mic(&PTK, sm->last_rx_eapol_key, 17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->last_rx_eapol_key_len) == 0) { 17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ok = 1; 17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) 17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ok) { 17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "invalid MIC in msg 2/4 of 4-Way Handshake"); 17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { 18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Verify that PMKR1Name from EAPOL-Key message 2/4 matches 18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * with the value we derived. 18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(sm->sup_pmk_r1_name, sm->pmk_r1_name, 18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PMK_NAME_LEN) != 0) { 18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PMKR1Name mismatch in FT 4-way " 18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "handshake"); 18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from " 18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Supplicant", 18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->sup_pmk_r1_name, WPA_PMK_NAME_LEN); 18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name", 18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmk_r1_name, WPA_PMK_NAME_LEN); 18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pending_1_of_4_timeout = 0; 18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm); 18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { 18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* PSK may have changed from the previous choice, so update 18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * state machine data based on whatever PSK was selected here. 18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->PMK, pmk, PMK_LEN); 18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->MICVerified = TRUE; 18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&sm->PTK, &PTK, sizeof(PTK)); 18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PTK_valid = TRUE; 18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, PTKCALCNEGOTIATING2) 18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING2, wpa_ptk); 18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutCtr = 0; 18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee80211w_kde_len(struct wpa_state_machine *sm) 18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->mgmt_frame_prot) { 18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 2 + RSN_SELECTOR_LEN + sizeof(struct wpa_igtk_kde); 18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) 18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_igtk_kde igtk; 18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *gsm = sm->group; 18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->mgmt_frame_prot) 18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt igtk.keyid[0] = gsm->GN_igtk; 18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt igtk.keyid[1] = 0; 18658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE || 18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, igtk.pn) < 0) 18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(igtk.pn, 0, sizeof(igtk.pn)); 18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN); 186961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->wpa_auth->conf.disable_gtk) { 187061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* 187161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Provide unique random IGTK to each STA to prevent use of 187261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * IGTK in the BSS. 187361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 187461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (random_get_bytes(igtk.igtk, WPA_IGTK_LEN) < 0) 187561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return pos; 187661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK, 18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (const u8 *) &igtk, sizeof(igtk), NULL, 0); 18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_IEEE80211W */ 18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee80211w_kde_len(struct wpa_state_machine *sm) 18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) 18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, PTKINITNEGOTIATING) 19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 190161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos, dummy_gtk[32]; 19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t gtk_len, kde_len; 19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *gsm = sm->group; 19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *wpa_ie; 19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int wpa_ie_len, secure, keyidx, encr = 0; 19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk); 19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutEvt = FALSE; 19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutCtr++; 19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->TimeoutCtr > (int) dot11RSNAConfigPairwiseUpdateCount) { 19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No point in sending the EAPOL-Key - we will disconnect 19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * immediately following this. */ 19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE], 19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GTK[GN], IGTK, [FTIE], [TIE * 2]) 19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(rsc, 0, WPA_KEY_RSC_LEN); 19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc); 19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */ 19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ie = sm->wpa_auth->wpa_ie; 19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ie_len = sm->wpa_auth->wpa_ie_len; 19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA && 19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) && 19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ie_len > wpa_ie[1] + 2 && wpa_ie[0] == WLAN_EID_RSN) { 19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* WPA-only STA, remove RSN IE */ 19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ie = wpa_ie + wpa_ie[1] + 2; 19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ie_len = wpa_ie[1] + 2; 19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "sending 3/4 msg of 4-Way Handshake"); 19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA2) { 19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* WPA2 send GTK in the 4-way handshake */ 19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt secure = 1; 19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gtk = gsm->GTK[gsm->GN - 1]; 19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gtk_len = gsm->GTK_len; 193961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->wpa_auth->conf.disable_gtk) { 194061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* 194161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Provide unique random GTK to each STA to prevent use 194261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * of GTK in the BSS. 194361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 194461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (random_get_bytes(dummy_gtk, gtk_len) < 0) 194561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 194661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gtk = dummy_gtk; 194761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keyidx = gsm->GN; 19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _rsc = rsc; 19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encr = 1; 19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* WPA does not include GTK in msg 3/4 */ 19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt secure = 0; 19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gtk = NULL; 19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gtk_len = 0; 19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keyidx = 0; 19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _rsc = NULL; 19581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (sm->rx_eapol_key_secure) { 19591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 19601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * It looks like Windows 7 supplicant tries to use 19611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Secure bit in msg 2/4 after having reported Michael 19621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * MIC failure and it then rejects the 4-way handshake 19631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * if msg 3/4 does not set Secure bit. Work around this 19641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * by setting the Secure bit here even in the case of 19651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * WPA if the supplicant used it first. 19661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 19671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 19681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "STA used Secure bit in WPA msg 2/4 - " 19691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "set Secure for 3/4 as workaround"); 19701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt secure = 1; 19711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len = wpa_ie_len + ieee80211w_kde_len(sm); 19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gtk) 19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len; 19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { 19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */ 19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len += 300; /* FTIE + 2 * TIE */ 19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde = os_malloc(kde_len); 19848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde == NULL) 19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = kde; 19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, wpa_ie, wpa_ie_len); 19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += wpa_ie_len; 19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { 19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res = wpa_insert_pmkid(kde, pos - kde, sm->pmk_r1_name); 19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "FT: Failed to insert " 19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PMKR1Name into RSN IE in EAPOL-Key data"); 19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(kde); 19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += res; 20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gtk) { 20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hdr[2]; 20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr[0] = keyidx & 0x03; 20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr[1] = 0; 20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, 20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gtk, gtk_len); 20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = ieee80211w_kde_add(sm, pos); 20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { 20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_auth_config *conf; 20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf = &sm->wpa_auth->conf; 20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wpa_write_ftie(conf, conf->r0_key_holder, 20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf->r0_key_holder_len, 20198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, NULL, pos, kde + kde_len - pos, 20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0); 20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE " 20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "into EAPOL-Key Key Data"); 20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(kde); 20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += res; 20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TIE[ReassociationDeadline] (TU) */ 20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = WLAN_EID_TIMEOUT_INTERVAL; 20318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 5; 20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE; 20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE32(pos, conf->reassociation_deadline); 20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 4; 20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TIE[KeyLifetime] (seconds) */ 20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = WLAN_EID_TIMEOUT_INTERVAL; 20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 5; 20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = WLAN_TIMEOUT_KEY_LIFETIME; 20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE32(pos, conf->r0_key_lifetime * 60); 20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 4; 20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_send_eapol(sm->wpa_auth, sm, 20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (secure ? WPA_KEY_INFO_SECURE : 0) | WPA_KEY_INFO_MIC | 20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL | 20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_KEY_TYPE, 20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _rsc, sm->ANonce, kde, pos - kde, keyidx, encr); 20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(kde); 20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20548d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, PTKINITDONE) 20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk); 20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->EAPOLKeyReceived = FALSE; 20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->Pair) { 20594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise); 20604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt int klen = wpa_cipher_key_len(sm->pairwise); 20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, 20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PTK.tk1, klen)) { 20638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sta_disconnect(sm->wpa_auth, sm->addr); 20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ 20678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pairwise_set = TRUE; 20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_auth->conf.wpa_ptk_rekey) { 20708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); 20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(sm->wpa_auth->conf. 20728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ptk_rekey, 0, wpa_rekey_ptk, 20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_auth, sm); 20748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { 20778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, 20788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_EAPOL_authorized, 1); 20798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (0 /* IBSS == TRUE */) { 20838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->keycount++; 20848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->keycount == 2) { 20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, 20868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_EAPOL_portValid, 1); 20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 20898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1); 20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyAvailable, 0); 20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyDone, 1); 20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA) 20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PInitAKeys = TRUE; 20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->has_GTK = TRUE; 20988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, 20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pairwise key handshake completed (%s)", 21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN"); 21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ft_push_pmk_r1(sm->wpa_auth, sm->addr); 21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STEP(WPA_PTK) 21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_authenticator *wpa_auth = sm->wpa_auth; 21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->Init) 21138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, INITIALIZE); 21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->Disconnect 21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* || FIX: dot11RSNAConfigSALifetime timeout */) { 21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, 21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA_PTK: sm->Disconnect"); 21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, DISCONNECT); 21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->DeauthenticationRequest) 21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, DISCONNECTED); 21228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->AuthenticationRequest) 21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, AUTHENTICATION); 21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->ReAuthenticationRequest) 21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, AUTHENTICATION2); 21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->PTKRequest) 21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKSTART); 21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else switch (sm->wpa_ptk_state) { 21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_INITIALIZE: 21308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 21318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_DISCONNECT: 21328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, DISCONNECTED); 21338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 21348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_DISCONNECTED: 21358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, INITIALIZE); 21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_AUTHENTICATION: 21388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, AUTHENTICATION2); 21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_AUTHENTICATION2: 21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) && 21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_get_eapol(sm->wpa_auth, sm->addr, 21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_EAPOL_keyRun) > 0) 21448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, INITPMK); 21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) 21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: && 802.1X::keyRun */) 21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, INITPSK); 21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_INITPMK: 21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_get_eapol(sm->wpa_auth, sm->addr, 21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_EAPOL_keyAvailable) > 0) 21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKSTART); 21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNA4WayHandshakeFailures++; 21558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, 21568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "INITPMK - keyAvailable = false"); 21578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, DISCONNECT); 21588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_INITPSK: 21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_get_psk(sm->wpa_auth, sm->addr, NULL)) 21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKSTART); 21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, 21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "no PSK configured for the STA"); 21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNA4WayHandshakeFailures++; 21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, DISCONNECT); 21688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_PTKSTART: 21718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && 21728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->EAPOLKeyPairwise) 21738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); 21748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->TimeoutCtr > 21758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) dot11RSNAConfigPairwiseUpdateCount) { 21768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNA4WayHandshakeFailures++; 21778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PTKSTART: Retry limit %d reached", 21798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dot11RSNAConfigPairwiseUpdateCount); 21808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, DISCONNECT); 21818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (sm->TimeoutEvt) 21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKSTART); 21838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_PTKCALCNEGOTIATING: 21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->MICVerified) 21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING2); 21878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && 21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->EAPOLKeyPairwise) 21898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); 21908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->TimeoutEvt) 21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKSTART); 21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_PTKCALCNEGOTIATING2: 21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKINITNEGOTIATING); 21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_PTKINITNEGOTIATING: 2197c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (sm->update_snonce) 2198c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); 2199c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && 2200c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sm->EAPOLKeyPairwise && sm->MICVerified) 22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKINITDONE); 22028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->TimeoutCtr > 22038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) dot11RSNAConfigPairwiseUpdateCount) { 22048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNA4WayHandshakeFailures++; 22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PTKINITNEGOTIATING: Retry limit %d " 22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "reached", 22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dot11RSNAConfigPairwiseUpdateCount); 22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, DISCONNECT); 22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (sm->TimeoutEvt) 22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKINITNEGOTIATING); 22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_PTKINITDONE: 22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 22158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 22178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22198d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK_GROUP, IDLE) 22208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 22218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK_GROUP, IDLE, wpa_ptk_group); 22228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->Init) { 22238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Init flag is not cleared here, so avoid busy 22248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * loop by claiming nothing changed. */ 22258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->changed = FALSE; 22268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GTimeoutCtr = 0; 22288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 22298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22318d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) 22328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 22338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rsc[WPA_KEY_RSC_LEN]; 22348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *gsm = sm->group; 22358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *kde, *pos, hdr[2]; 22368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t kde_len; 223761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 *gtk, dummy_gtk[32]; 22388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group); 22408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GTimeoutCtr++; 22428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->GTimeoutCtr > (int) dot11RSNAConfigGroupUpdateCount) { 22438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No point in sending the EAPOL-Key - we will disconnect 22448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * immediately following this. */ 22458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 22468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA) 22498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PInitAKeys = FALSE; 22508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutEvt = FALSE; 22518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */ 22528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(rsc, 0, WPA_KEY_RSC_LEN); 22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gsm->wpa_group_state == WPA_GROUP_SETKEYSDONE) 22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc); 22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 22568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "sending 1/2 msg of Group Key Handshake"); 22578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 225861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gtk = gsm->GTK[gsm->GN - 1]; 225961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->wpa_auth->conf.disable_gtk) { 226061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* 226161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Provide unique random GTK to each STA to prevent use 226261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * of GTK in the BSS. 226361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 226461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (random_get_bytes(dummy_gtk, gsm->GTK_len) < 0) 226561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 226661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gtk = dummy_gtk; 226761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 22688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA2) { 22698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len + 22708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee80211w_kde_len(sm); 22718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde = os_malloc(kde_len); 22728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde == NULL) 22738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 22748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = kde; 22768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr[0] = gsm->GN & 0x03; 22778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr[1] = 0; 22788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, 227961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gtk, gsm->GTK_len); 22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = ieee80211w_kde_add(sm, pos); 22818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 228261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt kde = gtk; 22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = kde + gsm->GTK_len; 22848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_send_eapol(sm->wpa_auth, sm, 22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC | 22888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_ACK | 22898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0), 22908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsc, gsm->GNonce, kde, pos - kde, gsm->GN, 1); 22918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA2) 22928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(kde); 22938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22968d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED) 22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK_GROUP, REKEYESTABLISHED, wpa_ptk_group); 22998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->EAPOLKeyReceived = FALSE; 23008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->GUpdateStationKeys) 23018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group->GKeyDoneStations--; 23028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GUpdateStationKeys = FALSE; 23038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GTimeoutCtr = 0; 23048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */ 23058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, 23068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "group key handshake completed (%s)", 23078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN"); 23088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->has_GTK = TRUE; 23098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23128d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK_GROUP, KEYERROR) 23138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK_GROUP, KEYERROR, wpa_ptk_group); 23158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->GUpdateStationKeys) 23168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group->GKeyDoneStations--; 23178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GUpdateStationKeys = FALSE; 23188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->Disconnect = TRUE; 23198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23228d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STEP(WPA_PTK_GROUP) 23238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->Init || sm->PtkGroupInit) { 23258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK_GROUP, IDLE); 23268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PtkGroupInit = FALSE; 23278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else switch (sm->wpa_ptk_group_state) { 23288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_GROUP_IDLE: 23298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->GUpdateStationKeys || 23308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (sm->wpa == WPA_VERSION_WPA && sm->PInitAKeys)) 23318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING); 23328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_GROUP_REKEYNEGOTIATING: 23348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && 23358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !sm->EAPOLKeyPairwise && sm->MICVerified) 23368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK_GROUP, REKEYESTABLISHED); 23378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->GTimeoutCtr > 23388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) dot11RSNAConfigGroupUpdateCount) 23398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK_GROUP, KEYERROR); 23408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->TimeoutEvt) 23418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING); 23428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_GROUP_KEYERROR: 23448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK_GROUP, IDLE); 23458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_GROUP_REKEYESTABLISHED: 23478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK_GROUP, IDLE); 23488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_gtk_update(struct wpa_authenticator *wpa_auth, 23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group) 23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); 23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(group->Counter, WPA_NONCE_LEN); 23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_gmk_to_gtk(group->GMK, "Group key expansion", 23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->addr, group->GNonce, 23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTK[group->GN - 1], group->GTK_len) < 0) 23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 23648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "GTK", 23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTK[group->GN - 1], group->GTK_len); 23668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) { 23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); 23708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(group->Counter, WPA_NONCE_LEN); 23718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion", 23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->addr, group->GNonce, 23738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->IGTK[group->GN_igtk - 4], 23748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_IGTK_LEN) < 0) 23758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IGTK", 23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->IGTK[group->GN_igtk - 4], WPA_IGTK_LEN); 23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 23808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 23828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth, 23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group) 23878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " 23898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "GTK_INIT (VLAN-ID %d)", group->vlan_id); 23908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->changed = FALSE; /* GInit is not cleared here; avoid loop */ 23918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->wpa_group_state = WPA_GROUP_GTK_INIT; 23928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* GTK[0..N] = 0 */ 23948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(group->GTK, 0, sizeof(group->GTK)); 23958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GN = 1; 23968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GM = 2; 23978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 23988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GN_igtk = 4; 23998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GM_igtk = 5; 24008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 24018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* GTK[GN] = CalcGTK() */ 24028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_gtk_update(wpa_auth, group); 24038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 24048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx) 24078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 240861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (ctx != NULL && ctx != sm->group) 240961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 241061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 24118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) { 24128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 24138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Not in PTKINITDONE; skip Group Key update"); 24148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GUpdateStationKeys = FALSE; 24158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 24168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->GUpdateStationKeys) { 24188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 24198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This should not really happen, so add a debug log entry. 24208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Since we clear the GKeyDoneStations before the loop, the 24218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * station needs to be counted here anyway. 24228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 24238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 24248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "GUpdateStationKeys was already set when " 24258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "marking station for GTK rekeying"); 24268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2428a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt /* Do not rekey GTK/IGTK when STA is in WNM-Sleep Mode */ 242961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->is_wnmsleep) 243061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 243161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 24328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group->GKeyDoneStations++; 24338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GUpdateStationKeys = TRUE; 24348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_step(sm); 24368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 24378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 24388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2440a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#ifdef CONFIG_WNM 2441a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt/* update GTK when exiting WNM-Sleep Mode */ 244261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm) 244361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 244461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->is_wnmsleep) 244561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 244661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 244761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_group_update_sta(sm, NULL); 244861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 244961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 245061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 245161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag) 245261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 245361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sm->is_wnmsleep = !!flag; 245461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 245561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 245661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 245761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos) 245861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 245961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_group *gsm = sm->group; 2460a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt u8 *start = pos; 246161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 246261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* 2463a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * GTK subelement: 246461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] | 2465a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Key[5..32] 246661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 2467a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *pos++ = WNM_SLEEP_SUBELEM_GTK; 2468a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *pos++ = 11 + gsm->GTK_len; 246961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* Key ID in B0-B1 of Key Info */ 2470a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt WPA_PUT_LE16(pos, gsm->GN & 0x03); 2471a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos += 2; 2472a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *pos++ = gsm->GTK_len; 2473a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, pos) != 0) 247461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 2475a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos += 8; 2476a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt os_memcpy(pos, gsm->GTK[gsm->GN - 1], gsm->GTK_len); 2477a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos += gsm->GTK_len; 247861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2479a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_printf(MSG_DEBUG, "WNM: GTK Key ID %u in WNM-Sleep Mode exit", 2480a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt gsm->GN); 2481a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WNM: GTK in WNM-Sleep Mode exit", 248261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gsm->GTK[gsm->GN - 1], gsm->GTK_len); 248361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2484a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return pos - start; 248561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 248661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 248761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 248861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_IEEE80211W 248961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos) 249061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 249161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_group *gsm = sm->group; 2492a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt u8 *start = pos; 249361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2494a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt /* 2495a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * IGTK subelement: 2496a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16] 2497a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt */ 2498a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *pos++ = WNM_SLEEP_SUBELEM_IGTK; 2499a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *pos++ = 2 + 6 + WPA_IGTK_LEN; 2500a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt WPA_PUT_LE16(pos, gsm->GN_igtk); 2501a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos += 2; 2502a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos) != 0) 250361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 2504a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos += 6; 250561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2506a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN); 2507a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos += WPA_IGTK_LEN; 250861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2509a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_printf(MSG_DEBUG, "WNM: IGTK Key ID %u in WNM-Sleep Mode exit", 2510a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt gsm->GN_igtk); 2511a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WNM: IGTK in WNM-Sleep Mode exit", 251261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN); 251361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2514a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return pos - start; 251561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 251661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 2517a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#endif /* CONFIG_WNM */ 251861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 251961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 25208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_group_setkeys(struct wpa_authenticator *wpa_auth, 25218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group) 25228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 25238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tmp; 25248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " 25268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SETKEYS (VLAN-ID %d)", group->vlan_id); 25278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->changed = TRUE; 25288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->wpa_group_state = WPA_GROUP_SETKEYS; 25298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTKReKey = FALSE; 25308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = group->GM; 25318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GM = group->GN; 25328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GN = tmp; 25338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 25348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = group->GM_igtk; 25358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GM_igtk = group->GN_igtk; 25368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GN_igtk = tmp; 25378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 25388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* "GKeyDoneStations = GNoStations" is done in more robust way by 25398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * counting the STAs that are marked with GUpdateStationKeys instead of 25408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * including all STAs that could be in not-yet-completed state. */ 25418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_gtk_update(wpa_auth, group); 25428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group->GKeyDoneStations) { 25448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "wpa_group_setkeys: Unexpected " 25458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "GKeyDoneStations=%d when starting new GTK rekey", 25468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GKeyDoneStations); 25478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GKeyDoneStations = 0; 25488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 254961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_auth_for_each_sta(wpa_auth, wpa_group_update_sta, group); 25508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "wpa_group_setkeys: GKeyDoneStations=%d", 25518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GKeyDoneStations); 25528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 25538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth, 25568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group) 25578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 25588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 25598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_set_key(wpa_auth, group->vlan_id, 25614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_cipher_to_alg(wpa_auth->conf.wpa_group), 25628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt broadcast_ether_addr, group->GN, 25638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTK[group->GN - 1], group->GTK_len) < 0) 25648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 25658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 25678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION && 25688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_key(wpa_auth, group->vlan_id, WPA_ALG_IGTK, 25698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt broadcast_ether_addr, group->GN_igtk, 25708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->IGTK[group->GN_igtk - 4], 25718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_IGTK_LEN) < 0) 25728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 25738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 25748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 25768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 25778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth, 25808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group) 25818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 25828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " 25838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SETKEYSDONE (VLAN-ID %d)", group->vlan_id); 25848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->changed = TRUE; 25858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->wpa_group_state = WPA_GROUP_SETKEYSDONE; 25868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_group_config_group_keys(wpa_auth, group) < 0) 25888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 25898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 25918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 25928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_group_sm_step(struct wpa_authenticator *wpa_auth, 25958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group) 25968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 25978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group->GInit) { 25988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_gtk_init(wpa_auth, group); 25998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (group->wpa_group_state == WPA_GROUP_GTK_INIT && 26008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTKAuthenticator) { 26018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_setkeysdone(wpa_auth, group); 26028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (group->wpa_group_state == WPA_GROUP_SETKEYSDONE && 26038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTKReKey) { 26048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_setkeys(wpa_auth, group); 26058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (group->wpa_group_state == WPA_GROUP_SETKEYS) { 26068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group->GKeyDoneStations == 0) 26078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_setkeysdone(wpa_auth, group); 26088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (group->GTKReKey) 26098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_setkeys(wpa_auth, group); 26108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 26118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_sm_step(struct wpa_state_machine *sm) 26158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 26178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 26188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->in_step_loop) { 26208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* This should not happen, but if it does, make sure we do not 26218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * end up freeing the state machine too early by exiting the 26228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * recursive call. */ 26238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "WPA: wpa_sm_step() called recursively"); 26248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 26258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 26268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->in_step_loop = 1; 26288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt do { 26298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pending_deinit) 26308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 26318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->changed = FALSE; 26338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_auth->group->changed = FALSE; 26348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_STEP_RUN(WPA_PTK); 26368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pending_deinit) 26378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 26388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_STEP_RUN(WPA_PTK_GROUP); 26398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pending_deinit) 26408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 26418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_sm_step(sm->wpa_auth, sm->group); 26428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } while (sm->changed || sm->wpa_auth->group->changed); 26438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->in_step_loop = 0; 26448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pending_deinit) { 26468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Completing pending STA state " 26478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "machine deinit for " MACSTR, MAC2STR(sm->addr)); 26488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_free_sta_sm(sm); 26498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 26508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 26518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 26528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx) 26568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm = eloop_ctx; 26588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_step(sm); 26598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_auth_sm_notify(struct wpa_state_machine *sm) 26638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 26658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 26668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL); 26678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_gtk_rekey(struct wpa_authenticator *wpa_auth) 26718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tmp, i; 26738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group; 26748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL) 26768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 26778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = wpa_auth->group; 26798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < 2; i++) { 26818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = group->GM; 26828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GM = group->GN; 26838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GN = tmp; 26848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 26858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = group->GM_igtk; 26868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GM_igtk = group->GN_igtk; 26878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GN_igtk = tmp; 26888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 26898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_gtk_update(wpa_auth, group); 26901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_group_config_group_keys(wpa_auth, group); 26918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 26928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * wpa_bool_txt(int bool) 26968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return bool ? "TRUE" : "FALSE"; 26988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RSN_SUITE "%02x-%02x-%02x-%d" 27028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RSN_SUITE_ARG(s) \ 27038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff 27048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen) 27068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 27078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int len = 0, ret; 27088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char pmkid_txt[PMKID_LEN * 2 + 1]; 27098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_RSN_PREAUTH 27108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const int preauth = 1; 27118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_RSN_PREAUTH */ 27128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const int preauth = 0; 27138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_RSN_PREAUTH */ 27148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL) 27168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 27178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, 27198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAOptionImplemented=TRUE\n" 27208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAPreauthenticationImplemented=%s\n" 27218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAEnabled=%s\n" 27228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAPreauthenticationEnabled=%s\n", 27238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_bool_txt(preauth), 27248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_bool_txt(wpa_auth->conf.wpa & WPA_PROTO_RSN), 27258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_bool_txt(wpa_auth->conf.rsn_preauth)); 27268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || (size_t) ret >= buflen - len) 27278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 27288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 27298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt), 27318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNAPMKIDUsed, PMKID_LEN); 27328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf( 27348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf + len, buflen - len, 27358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigVersion=%u\n" 27368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigPairwiseKeysSupported=9999\n" 27378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: dot11RSNAConfigGroupCipher */ 27388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: dot11RSNAConfigGroupRekeyMethod */ 27398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: dot11RSNAConfigGroupRekeyTime */ 27408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: dot11RSNAConfigGroupRekeyPackets */ 27418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigGroupRekeyStrict=%u\n" 27428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigGroupUpdateCount=%u\n" 27438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigPairwiseUpdateCount=%u\n" 27448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigGroupCipherSize=%u\n" 27458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigPMKLifetime=%u\n" 27468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigPMKReauthThreshold=%u\n" 27478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigNumberOfPTKSAReplayCounters=0\n" 27488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigSATimeout=%u\n" 27498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n" 27508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n" 27518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n" 27528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAPMKIDUsed=%s\n" 27538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n" 27548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n" 27558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n" 27568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNATKIPCounterMeasuresInvoked=%u\n" 27578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNA4WayHandshakeFailures=%u\n" 27588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n", 27598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_VERSION, 27608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !!wpa_auth->conf.wpa_strict_rekey, 27618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dot11RSNAConfigGroupUpdateCount, 27628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dot11RSNAConfigPairwiseUpdateCount, 27634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_cipher_key_len(wpa_auth->conf.wpa_group) * 8, 27648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dot11RSNAConfigPMKLifetime, 27658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dot11RSNAConfigPMKReauthThreshold, 27668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dot11RSNAConfigSATimeout, 27678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteSelected), 27688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherSelected), 27698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherSelected), 27708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmkid_txt, 27718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteRequested), 27728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherRequested), 27738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherRequested), 27748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNATKIPCounterMeasuresInvoked, 27758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNA4WayHandshakeFailures); 27768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || (size_t) ret >= buflen - len) 27778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 27788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 27798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot11RSNAConfigPairwiseCiphersTable */ 27818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot11RSNAConfigAuthenticationSuitesTable */ 27828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Private MIB */ 27848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, "hostapdWPAGroupState=%d\n", 27858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->group->wpa_group_state); 27868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || (size_t) ret >= buflen - len) 27878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 27888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 27898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 27918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 27928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen) 27958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 27968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int len = 0, ret; 27978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 pairwise = 0; 27988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 28008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 28018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: FF-FF-FF-FF-FF-FF entry for broadcast/multicast stats */ 28038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* dot11RSNAStatsEntry */ 28058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt pairwise = wpa_cipher_to_suite(sm->wpa == WPA_VERSION_WPA2 ? 28074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt WPA_PROTO_RSN : WPA_PROTO_WPA, 28084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->pairwise); 28094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (pairwise == 0) 28108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 28118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf( 28138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf + len, buflen - len, 28148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot11RSNAStatsIndex */ 28158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAStatsSTAAddress=" MACSTR "\n" 28168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAStatsVersion=1\n" 28178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAStatsSelectedPairwiseCipher=" RSN_SUITE "\n" 28188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot11RSNAStatsTKIPICVErrors */ 28198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAStatsTKIPLocalMICFailures=%u\n" 28208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAStatsTKIPRemoteMICFailures=%u\n" 28218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot11RSNAStatsCCMPReplays */ 28228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot11RSNAStatsCCMPDecryptErrors */ 28238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot11RSNAStatsTKIPReplays */, 28248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(sm->addr), 28258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SUITE_ARG(pairwise), 28268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAStatsTKIPLocalMICFailures, 28278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAStatsTKIPRemoteMICFailures); 28288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || (size_t) ret >= buflen - len) 28298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 28308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 28318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Private MIB */ 28338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, 28348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "hostapdWPAPTKState=%d\n" 28358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "hostapdWPAPTKGroupState=%d\n", 28368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ptk_state, 28378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ptk_group_state); 28388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || (size_t) ret >= buflen - len) 28398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 28408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 28418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 28438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 28448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth) 28478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 28488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth) 28498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNATKIPCounterMeasuresInvoked++; 28508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 28518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_pairwise_set(struct wpa_state_machine *sm) 28548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 28558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm && sm->pairwise_set; 28568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 28578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_get_pairwise(struct wpa_state_machine *sm) 28608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 28618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->pairwise; 28628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 28638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm) 28668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 28678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 28688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 28698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->wpa_key_mgmt; 28708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 28718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_sta_wpa_version(struct wpa_state_machine *sm) 28748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 28758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 28768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 28778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->wpa; 28788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 28798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm, 28828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *entry) 28838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 28848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL || sm->pmksa != entry) 28858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 28868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmksa = NULL; 28878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 28888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 28898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct rsn_pmksa_cache_entry * 28928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_auth_sta_get_pmksa(struct wpa_state_machine *sm) 28938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 28948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm ? sm->pmksa : NULL; 28958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 28968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm) 28998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 29008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm) 29018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAStatsTKIPLocalMICFailures++; 29028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 29038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, size_t *len) 29068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 29078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL) 29088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 29098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = wpa_auth->wpa_ie_len; 29108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->wpa_ie; 29118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 29128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk, 29158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int session_timeout, struct eapol_state_machine *eapol) 29168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2917c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt if (sm == NULL || sm->wpa != WPA_VERSION_WPA2 || 2918c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt sm->wpa_auth->conf.disable_pmksa_caching) 29198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 29208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, PMK_LEN, 29228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_auth->addr, sm->addr, session_timeout, 29238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol, sm->wpa_key_mgmt)) 29248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 29258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 29278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 29288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth, 29318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pmk, size_t len, const u8 *sta_addr, 29328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int session_timeout, 29338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *eapol) 29348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 29358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL) 29368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 29378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, len, wpa_auth->addr, 29398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta_addr, session_timeout, eapol, 29408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_MGMT_IEEE8021X)) 29418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 29428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 29448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 29458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2947f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidtvoid wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth, 2948f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt const u8 *sta_addr) 2949f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt{ 2950f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt struct rsn_pmksa_cache_entry *pmksa; 2951f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt 2952f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt if (wpa_auth == NULL || wpa_auth->pmksa == NULL) 2953f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt return; 2954f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, NULL); 2955f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt if (pmksa) { 2956f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Remove PMKSA cache entry for " 2957f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt MACSTR " based on request", MAC2STR(sta_addr)); 2958f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt pmksa_cache_free_entry(wpa_auth->pmksa, pmksa); 2959f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt } 2960f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt} 2961f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt 2962f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt 29638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_group * 29648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id) 29658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 29668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group; 29678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL || wpa_auth->group == NULL) 29698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 29708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Add group state machine for VLAN-ID %d", 29728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vlan_id); 29731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt group = wpa_group_init(wpa_auth, vlan_id, 0); 29748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group == NULL) 29758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 29768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->next = wpa_auth->group->next; 29788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->group->next = group; 29798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return group; 29818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 29828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id) 29858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 29868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group; 29878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL || sm->wpa_auth == NULL) 29898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 29908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = sm->wpa_auth->group; 29928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (group) { 29938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group->vlan_id == vlan_id) 29948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 29958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = group->next; 29968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 29978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group == NULL) { 29998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = wpa_auth_add_group(sm->wpa_auth, vlan_id); 30008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group == NULL) 30018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 30028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 30038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->group == group) 30058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 30068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR " to use group state " 30088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "machine for VLAN ID %d", MAC2STR(sm->addr), vlan_id); 30098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group = group; 30118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 30128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 30138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth, 30168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm, int ack) 30178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 30188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL || sm == NULL) 30198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 30208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key TX status for STA " MACSTR 30218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " ack=%d", MAC2STR(sm->addr), ack); 30228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pending_1_of_4_timeout && ack) { 30238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 30248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Some deployed supplicant implementations update their SNonce 30258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * for each EAPOL-Key 2/4 message even within the same 4-way 30268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * handshake and then fail to use the first SNonce when 30278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * deriving the PTK. This results in unsuccessful 4-way 30288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * handshake whenever the relatively short initial timeout is 30298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * reached and EAPOL-Key 1/4 is retransmitted. Try to work 30308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * around this by increasing the timeout now that we know that 30318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the station has received the frame. 30328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 30338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int timeout_ms = eapol_key_timeout_subseq; 30348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Increase initial EAPOL-Key 1/4 " 30358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "timeout by %u ms because of acknowledged frame", 30368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeout_ms); 30378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm); 30388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(timeout_ms / 1000, 30398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (timeout_ms % 1000) * 1000, 30408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_send_eapol_timeout, wpa_auth, sm); 30418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 30428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3043d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 3044d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 3045d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtint wpa_auth_uses_sae(struct wpa_state_machine *sm) 3046d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt{ 3047d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (sm == NULL) 3048d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return 0; 3049d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return wpa_key_mgmt_sae(sm->wpa_key_mgmt); 3050d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt} 3051