wpa_auth.c revision 61d9df3e62aaa0e87ad05452fcb95142159a17b6
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 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline void 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) 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->cb.mic_failure_report(wpa_auth->cb.ctx, addr); 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline void wpa_auth_set_eapol(struct wpa_authenticator *wpa_auth, 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, wpa_eapol_variable var, 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int value) 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.set_eapol) 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->cb.set_eapol(wpa_auth->cb.ctx, addr, var, value); 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline int wpa_auth_get_eapol(struct wpa_authenticator *wpa_auth, 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, wpa_eapol_variable var) 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.get_eapol == NULL) 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->cb.get_eapol(wpa_auth->cb.ctx, addr, var); 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth, 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, const u8 *prev_psk) 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.get_psk == NULL) 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->cb.get_psk(wpa_auth->cb.ctx, addr, prev_psk); 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline int wpa_auth_get_msk(struct wpa_authenticator *wpa_auth, 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, u8 *msk, size_t *len) 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.get_msk == NULL) 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->cb.get_msk(wpa_auth->cb.ctx, addr, msk, len); 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int vlan_id, 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wpa_alg alg, const u8 *addr, int idx, 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key, size_t key_len) 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.set_key == NULL) 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->cb.set_key(wpa_auth->cb.ctx, vlan_id, alg, addr, idx, 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key, key_len); 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth, 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, int idx, u8 *seq) 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.get_seqnum == NULL) 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->cb.get_seqnum(wpa_auth->cb.ctx, addr, idx, seq); 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline int 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr, 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *data, size_t data_len, int encrypt) 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.send_eapol == NULL) 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->cb.send_eapol(wpa_auth->cb.ctx, addr, data, data_len, 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encrypt); 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth, 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int (*cb)(struct wpa_state_machine *sm, void *ctx), 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *cb_ctx) 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.for_each_sta == NULL) 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->cb.for_each_sta(wpa_auth->cb.ctx, cb, cb_ctx); 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth, 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int (*cb)(struct wpa_authenticator *a, void *ctx), 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *cb_ctx) 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.for_each_auth == NULL) 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->cb.for_each_auth(wpa_auth->cb.ctx, cb, cb_ctx); 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr, 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt logger_level level, const char *txt) 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.logger == NULL) 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->cb.logger(wpa_auth->cb.ctx, addr, level, txt); 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr, 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt logger_level level, const char *fmt, ...) 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *format; 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int maxlen; 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt va_list ap; 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.logger == NULL) 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt maxlen = os_strlen(fmt) + 100; 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt format = os_malloc(maxlen); 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!format) 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt va_start(ap, fmt); 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vsnprintf(format, maxlen, fmt, ap); 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt va_end(ap); 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, addr, level, format); 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(format); 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth, 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr) 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.disconnect == NULL) 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR, MAC2STR(addr)); 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->cb.disconnect(wpa_auth->cb.ctx, addr, 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_REASON_PREV_AUTH_NOT_VALID); 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_use_aes_cmac(struct wpa_state_machine *sm) 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 1; 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_sha256(sm->wpa_key_mgmt)) 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 1; 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx) 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_authenticator *wpa_auth = eloop_ctx; 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(wpa_auth->group->GMK, WPA_GMK_LEN)) { 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Failed to get random data for WPA " 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "initialization."); 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "GMK rekeyd"); 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "GMK", 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->group->GMK, WPA_GMK_LEN); 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->conf.wpa_gmk_rekey) { 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0, 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_rekey_gmk, wpa_auth, NULL); 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx) 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_authenticator *wpa_auth = eloop_ctx; 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group; 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "rekeying GTK"); 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (group = wpa_auth->group; group; group = group->next) { 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTKReKey = TRUE; 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt do { 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->changed = FALSE; 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_sm_step(wpa_auth, group); 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } while (group->changed); 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->conf.wpa_group_rekey) { 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, wpa_rekey_gtk, wpa_auth, NULL); 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_rekey_ptk(void *eloop_ctx, void *timeout_ctx) 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_authenticator *wpa_auth = eloop_ctx; 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm = timeout_ctx; 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "rekeying PTK"); 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_request_new_ptk(sm); 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_step(sm); 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_auth_pmksa_clear_cb(struct wpa_state_machine *sm, void *ctx) 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pmksa == ctx) 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmksa = NULL; 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_auth_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry, 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *ctx) 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_authenticator *wpa_auth = ctx; 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_for_each_sta(wpa_auth, wpa_auth_pmksa_clear_cb, entry); 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_group_set_key_len(struct wpa_group *group, int cipher) 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (cipher) { 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_CCMP: 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTK_len = 16; 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 28761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt case WPA_CIPHER_GCMP: 28861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt group->GTK_len = 16; 28961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_TKIP: 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTK_len = 32; 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_WEP104: 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTK_len = 13; 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_WEP40: 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTK_len = 5; 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_group_init_gmk_and_counter(struct wpa_authenticator *wpa_auth, 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group) 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 buf[ETH_ALEN + 8 + sizeof(group)]; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rkey[32]; 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(group->GMK, WPA_GMK_LEN) < 0) 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "GMK", group->GMK, WPA_GMK_LEN); 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Counter = PRF-256(Random number, "Init Counter", 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Local MAC Address || Time) 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf, wpa_auth->addr, ETH_ALEN); 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_get_ntp_timestamp(buf + ETH_ALEN); 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf + ETH_ALEN + 8, &group, sizeof(group)); 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(rkey, sizeof(rkey)) < 0) 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sha1_prf(rkey, sizeof(rkey), "Init Counter", buf, sizeof(buf), 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->Counter, WPA_NONCE_LEN) < 0) 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "Key Counter", 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->Counter, WPA_NONCE_LEN); 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth, 3341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int vlan_id, int delay_init) 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group; 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = os_zalloc(sizeof(struct wpa_group)); 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group == NULL) 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTKAuthenticator = TRUE; 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->vlan_id = vlan_id; 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_set_key_len(group, wpa_auth->conf.wpa_group); 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_pool_ready() != 1) { 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPA: Not enough entropy in random pool " 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for secure operations - update keys later when " 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the first station connects"); 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Set initial GMK/Counter value here. The actual values that will be 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * used in negotiations will be set once the first station tries to 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * connect. This allows more time for collecting additional randomness 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * on embedded devices. 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0) { 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Failed to get random data for WPA " 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "initialization."); 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(group); 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GInit = TRUE; 3671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (delay_init) { 3681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Delay group state machine start " 3691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "until Beacon frames have been configured"); 3701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Initialization is completed in wpa_init_keys(). */ 3711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else { 3721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_group_sm_step(wpa_auth, group); 3731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt group->GInit = FALSE; 3741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_group_sm_step(wpa_auth, group); 3751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return group; 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_init - Initialize WPA authenticator 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: Authenticator address 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @conf: Configuration for WPA authenticator 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cb: Callback functions for WPA authenticator 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to WPA authenticator data or %NULL on failure 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_authenticator * wpa_init(const u8 *addr, 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_auth_config *conf, 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_auth_callbacks *cb) 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_authenticator *wpa_auth; 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth = os_zalloc(sizeof(struct wpa_authenticator)); 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL) 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wpa_auth->addr, addr, ETH_ALEN); 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&wpa_auth->conf, conf, sizeof(*conf)); 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&wpa_auth->cb, cb, sizeof(*cb)); 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_gen_wpa_ie(wpa_auth)) { 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not generate WPA IE."); 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth); 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_auth->group = wpa_group_init(wpa_auth, 0, 1); 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->group == NULL) { 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth->wpa_ie); 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth); 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->pmksa = pmksa_cache_auth_init(wpa_auth_pmksa_free_cb, 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth); 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->pmksa == NULL) { 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "PMKSA cache initialization failed."); 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth->wpa_ie); 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth); 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->ft_pmk_cache = wpa_ft_pmk_cache_init(); 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->ft_pmk_cache == NULL) { 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "FT PMK cache initialization failed."); 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth->wpa_ie); 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_cache_auth_deinit(wpa_auth->pmksa); 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth); 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->conf.wpa_gmk_rekey) { 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0, 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_rekey_gmk, wpa_auth, NULL); 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->conf.wpa_group_rekey) { 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, 0, 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_rekey_gtk, wpa_auth, NULL); 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth; 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint wpa_init_keys(struct wpa_authenticator *wpa_auth) 4491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 4501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_group *group = wpa_auth->group; 4511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Start group state machine to set initial " 4531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "keys"); 4541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_group_sm_step(wpa_auth, group); 4551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt group->GInit = FALSE; 4561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_group_sm_step(wpa_auth, group); 4571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 4581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 4591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_deinit - Deinitialize WPA authenticator 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_auth: Pointer to WPA authenticator data from wpa_init() 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_deinit(struct wpa_authenticator *wpa_auth) 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group, *prev; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_rekey_gmk, wpa_auth, NULL); 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL); 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (wpa_auth->stsl_negotiations) 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_stsl_remove(wpa_auth, wpa_auth->stsl_negotiations); 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_cache_auth_deinit(wpa_auth->pmksa); 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ft_pmk_cache_deinit(wpa_auth->ft_pmk_cache); 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->ft_pmk_cache = NULL; 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth->wpa_ie); 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = wpa_auth->group; 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (group) { 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = group; 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = group->next; 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(prev); 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth); 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_reconfig - Update WPA authenticator configuration 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_auth: Pointer to WPA authenticator data from wpa_init() 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @conf: Configuration for WPA authenticator 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_reconfig(struct wpa_authenticator *wpa_auth, 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_auth_config *conf) 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group; 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL) 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&wpa_auth->conf, conf, sizeof(*conf)); 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_gen_wpa_ie(wpa_auth)) { 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not generate WPA IE."); 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Reinitialize GTK to make sure it is suitable for the new 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * configuration. 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = wpa_auth->group; 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_set_key_len(group, wpa_auth->conf.wpa_group); 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GInit = TRUE; 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_sm_step(wpa_auth, group); 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GInit = FALSE; 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_sm_step(wpa_auth, group); 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_state_machine * 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr) 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm; 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm = os_zalloc(sizeof(struct wpa_state_machine)); 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->addr, addr, ETH_ALEN); 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_auth = wpa_auth; 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group = wpa_auth->group; 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm; 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm) 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->ft_completed) { 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FT authentication already completed - do not " 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "start 4-way handshake"); 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->started) { 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&sm->key_replay, 0, sizeof(sm->key_replay)); 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ReAuthenticationRequest = TRUE; 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_sm_step(sm); 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "start authentication"); 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->started = 1; 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->Init = TRUE; 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_step(sm) == 1) 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; /* should not really happen */ 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->Init = FALSE; 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->AuthenticationRequest = TRUE; 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_sm_step(sm); 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_auth_sta_no_wpa(struct wpa_state_machine *sm) 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* WPA/RSN was not used - clear WPA state. This is needed if the STA 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * reassociates back to the same AP while the previous entry for the 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * STA has not yet been removed. */ 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_key_mgmt = 0; 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_free_sta_sm(struct wpa_state_machine *sm) 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->GUpdateStationKeys) { 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group->GKeyDoneStations--; 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GUpdateStationKeys = FALSE; 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->assoc_resp_ftie); 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->last_rx_eapol_key); 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->wpa_ie); 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm); 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_auth_sta_deinit(struct wpa_state_machine *sm) 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) { 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "strict rekeying - force GTK rekey since STA " 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "is leaving"); 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_rekey_gtk, sm->wpa_auth, NULL); 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(0, 500000, wpa_rekey_gtk, sm->wpa_auth, 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL); 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm); 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pending_1_of_4_timeout = 0; 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_sm_call_step, sm, NULL); 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->in_step_loop) { 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Must not free state machine while wpa_sm_step() is running. 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Freeing will be completed in the end of wpa_sm_step(). */ 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Registering pending STA state " 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "machine deinit for " MACSTR, MAC2STR(sm->addr)); 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pending_deinit = 1; 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_free_sta_sm(sm); 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_request_new_ptk(struct wpa_state_machine *sm) 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PTKRequest = TRUE; 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PTK_valid = 0; 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 647c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic int wpa_replay_counter_valid(struct wpa_key_replay_counter *ctr, 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *replay_counter) 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { 652c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (!ctr[i].valid) 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 654c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (os_memcmp(replay_counter, ctr[i].counter, 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN) == 0) 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 662c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic void wpa_replay_counter_mark_invalid(struct wpa_key_replay_counter *ctr, 663c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt const u8 *replay_counter) 664c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{ 665c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt int i; 666c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { 667c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (ctr[i].valid && 668c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt (replay_counter == NULL || 669c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt os_memcmp(replay_counter, ctr[i].counter, 670c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt WPA_REPLAY_COUNTER_LEN) == 0)) 671c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt ctr[i].valid = FALSE; 672c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 673c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt} 674c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 675c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth, 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm, 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *kde) 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data ie; 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_mdie *mdie; 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0 || 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie.num_pmkid != 1 || ie.pmkid == NULL) { 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "FT: No PMKR1Name in " 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FT 4-way handshake message 2/4"); 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->sup_pmk_r1_name, ie.pmkid, PMKID_LEN); 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Supplicant", 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->sup_pmk_r1_name, PMKID_LEN); 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!kde->mdie || !kde->ftie) { 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "FT: No %s in FT 4-way handshake " 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message 2/4", kde->mdie ? "FTIE" : "MDIE"); 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mdie = (struct rsn_mdie *) (kde->mdie + 2); 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde->mdie[1] < sizeof(struct rsn_mdie) || 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(wpa_auth->conf.mobility_domain, mdie->mobility_domain, 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MOBILITY_DOMAIN_ID_LEN) != 0) { 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "FT: MDIE mismatch"); 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->assoc_resp_ftie && 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (kde->ftie[1] != sm->assoc_resp_ftie[1] || 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(kde->ftie, sm->assoc_resp_ftie, 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + sm->assoc_resp_ftie[1]) != 0)) { 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "FT: FTIE mismatch"); 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 2/4", 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde->ftie, kde->ftie_len); 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)AssocResp", 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->assoc_resp_ftie, 2 + sm->assoc_resp_ftie[1]); 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void wpa_receive_error_report(struct wpa_authenticator *wpa_auth, 7271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_state_machine *sm, int group) 7281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 7291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Supplicant reported a Michael MIC error */ 7301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, 7311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "received EAPOL-Key Error Request " 7321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "(STA detected Michael MIC failure (group=%d))", 7331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt group); 7341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (group && wpa_auth->conf.wpa_group != WPA_CIPHER_TKIP) { 7361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 7371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "ignore Michael MIC failure report since " 7381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "group cipher is not TKIP"); 7391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else if (!group && sm->pairwise != WPA_CIPHER_TKIP) { 7401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 7411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "ignore Michael MIC failure report since " 7421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "pairwise cipher is not TKIP"); 7431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else { 7441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_auth_mic_failure_report(wpa_auth, sm->addr); 7451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt sm->dot11RSNAStatsTKIPRemoteMICFailures++; 7461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_auth->dot11RSNAStatsTKIPRemoteMICFailures++; 7471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 7481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 7501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Error report is not a request for a new key handshake, but since 7511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Authenticator may do it, let's change the keys now anyway. 7521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 7531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_request_new_ptk(sm); 7541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 7551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_receive(struct wpa_authenticator *wpa_auth, 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm, 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *data, size_t data_len) 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee802_1x_hdr *hdr; 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *key; 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info, key_data_length; 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST, 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SMK_M1, SMK_M3, SMK_ERROR } msg; 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *msgtxt; 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ft; 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *eapol_key_ie; 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t eapol_key_ie_len; 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data_len < sizeof(*hdr) + sizeof(*key)) 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct ieee802_1x_hdr *) data; 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = (struct wpa_eapol_key *) (hdr + 1); 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = WPA_GET_BE16(key->key_info); 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_data_length = WPA_GET_BE16(key->key_data_length); 7821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR 7831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " key_info=0x%x type=%u key_data_length=%u", 7841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(sm->addr), key_info, key->type, key_data_length); 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_data_length > data_len - sizeof(*hdr) - sizeof(*key)) { 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPA: Invalid EAPOL-Key frame - " 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "key_data overflow (%d > %lu)", 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_data_length, 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) (data_len - sizeof(*hdr) - 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(*key))); 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA2) { 795c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (key->type == EAPOL_KEY_TYPE_WPA) { 796c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 797c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * Some deployed station implementations seem to send 798c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * msg 4/4 with incorrect type value in WPA2 mode. 799c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 800c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_DEBUG, "Workaround: Allow EAPOL-Key " 801c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "with unexpected WPA type in RSN mode"); 802c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } else if (key->type != EAPOL_KEY_TYPE_RSN) { 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with " 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unexpected type %d in RSN mode", 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->type); 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key->type != EAPOL_KEY_TYPE_WPA) { 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with " 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unexpected type %d in WPA mode", 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->type); 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Received Key Nonce", key->key_nonce, 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_NONCE_LEN); 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Received Replay Counter", 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->replay_counter, WPA_REPLAY_COUNTER_LEN); 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: verify that the EAPOL-Key frame was encrypted if pairwise keys 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * are set */ 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((key_info & (WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_REQUEST)) == 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_REQUEST)) { 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_ERROR) { 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = SMK_ERROR; 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msgtxt = "SMK Error"; 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = SMK_M1; 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msgtxt = "SMK M1"; 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) { 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = SMK_M3; 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msgtxt = "SMK M3"; 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_info & WPA_KEY_INFO_REQUEST) { 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = REQUEST; 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msgtxt = "Request"; 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (!(key_info & WPA_KEY_INFO_KEY_TYPE)) { 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = GROUP_2; 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msgtxt = "2/2 Group"; 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_data_length == 0) { 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = PAIRWISE_4; 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msgtxt = "4/4 Pairwise"; 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = PAIRWISE_2; 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msgtxt = "2/4 Pairwise"; 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: key_info type validation for PeerKey */ 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == REQUEST || msg == PAIRWISE_2 || msg == PAIRWISE_4 || 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg == GROUP_2) { 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 ver = key_info & WPA_KEY_INFO_TYPE_MASK; 85561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->pairwise == WPA_CIPHER_CCMP || 85661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sm->pairwise == WPA_CIPHER_GCMP) { 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_use_aes_cmac(sm) && 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt LOGGER_WARNING, 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "advertised support for " 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "AES-128-CMAC, but did not " 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "use it"); 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_use_aes_cmac(sm) && 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt LOGGER_WARNING, 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "did not use HMAC-SHA1-AES " 87261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "with CCMP/GCMP"); 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_REQUEST) { 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->req_replay_counter_used && 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(key->replay_counter, sm->req_replay_counter, 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN) <= 0) { 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING, 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key request with " 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "replayed counter"); 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(key_info & WPA_KEY_INFO_REQUEST) && 890c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt !wpa_replay_counter_valid(sm->key_replay, key->replay_counter)) { 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 892c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 893c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (msg == PAIRWISE_2 && 894c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_replay_counter_valid(sm->prev_key_replay, 895c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt key->replay_counter) && 896c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING && 897c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt os_memcmp(sm->SNonce, key->key_nonce, WPA_NONCE_LEN) != 0) 898c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt { 899c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 900c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * Some supplicant implementations (e.g., Windows XP 901c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * WZC) update SNonce for each EAPOL-Key 2/4. This 902c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * breaks the workaround on accepting any of the 903c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * pending requests, so allow the SNonce to be updated 904c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * even if we have already sent out EAPOL-Key 3/4. 905c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 906c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, 907c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "Process SNonce update from STA " 908c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "based on retransmitted EAPOL-Key " 909c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "1/4"); 910c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sm->update_snonce = 1; 911c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_replay_counter_mark_invalid(sm->prev_key_replay, 912c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt key->replay_counter); 913c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt goto continue_processing; 914c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 915c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 916c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (msg == PAIRWISE_2 && 917c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_replay_counter_valid(sm->prev_key_replay, 918c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt key->replay_counter) && 919c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING) { 920c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, 921c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "ignore retransmitted EAPOL-Key %s - " 922c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "SNonce did not change", msgtxt); 923c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } else { 924c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, 925c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "received EAPOL-Key %s with " 926c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "unexpected replay counter", msgtxt); 927c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->key_replay[i].valid) 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "pending replay counter", 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->key_replay[i].counter, 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "received replay counter", 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->replay_counter, WPA_REPLAY_COUNTER_LEN); 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 940c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtcontinue_processing: 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (msg) { 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PAIRWISE_2: 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_ptk_state != WPA_PTK_PTKSTART && 944c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sm->wpa_ptk_state != WPA_PTK_PTKCALCNEGOTIATING && 945c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt (!sm->update_snonce || 946c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING)) { 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key msg 2/4 in " 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "invalid state (%d) - dropped", 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ptk_state); 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt random_add_randomness(key->key_nonce, WPA_NONCE_LEN); 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->group->reject_4way_hs_for_entropy) { 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The system did not have enough entropy to generate 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * strong random numbers. Reject the first 4-way 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * handshake(s) and collect some entropy based on the 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * information from it. Once enough entropy is 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * available, the next atempt will trigger GMK/Key 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Counter update and the station will be allowed to 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * continue. 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Reject 4-way handshake to " 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "collect more entropy for random number " 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "generation"); 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt random_mark_pool_ready(); 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sta_disconnect(wpa_auth, sm->addr); 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_parse_kde_ies((u8 *) (key + 1), key_data_length, 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &kde) < 0) { 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key msg 2/4 with " 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "invalid Key Data contents"); 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie) { 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_key_ie = kde.rsn_ie; 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_key_ie_len = kde.rsn_ie_len; 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_key_ie = kde.wpa_ie; 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_key_ie_len = kde.wpa_ie_len; 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ft = sm->wpa == WPA_VERSION_WPA2 && 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_key_mgmt_ft(sm->wpa_key_mgmt); 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_ie == NULL || 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_compare_rsn_ie(ft, 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ie, sm->wpa_ie_len, 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_key_ie, eapol_key_ie_len)) { 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA IE from (Re)AssocReq did not " 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "match with msg 2/4"); 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_ie) { 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA IE in AssocReq", 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ie, sm->wpa_ie_len); 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA IE in msg 2/4", 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_key_ie, eapol_key_ie_len); 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* MLME-DEAUTHENTICATE.request */ 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sta_disconnect(wpa_auth, sm->addr); 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) { 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sta_disconnect(wpa_auth, sm->addr); 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PAIRWISE_4: 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING || 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !sm->PTK_valid) { 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key msg 4/4 in " 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "invalid state (%d) - dropped", 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ptk_state); 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case GROUP_2: 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_ptk_group_state != WPA_PTK_GROUP_REKEYNEGOTIATING 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt || !sm->PTK_valid) { 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key msg 2/2 in " 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "invalid state (%d) - dropped", 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ptk_group_state); 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SMK_M1: 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SMK_M3: 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SMK_ERROR: 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_auth->conf.peerkey) { 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: SMK M1/M3/Error, but " 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PeerKey use disabled - ignoring message"); 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->PTK_valid) { 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key msg SMK in " 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "invalid state - dropped"); 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_PEERKEY */ 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SMK_M1: 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SMK_M3: 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SMK_ERROR: 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; /* STSL disabled - ignore SMK messages */ 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case REQUEST: 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key frame (%s)", msgtxt); 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_ACK) { 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received invalid EAPOL-Key: Key Ack set"); 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(key_info & WPA_KEY_INFO_MIC)) { 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received invalid EAPOL-Key: Key MIC not set"); 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->MICVerified = FALSE; 1073c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (sm->PTK_valid && !sm->update_snonce) { 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_verify_key_mic(&sm->PTK, data, data_len)) { 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key with invalid MIC"); 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->MICVerified = TRUE; 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm); 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pending_1_of_4_timeout = 0; 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_REQUEST) { 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->MICVerified) { 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->req_replay_counter_used = 1; 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->req_replay_counter, key->replay_counter, 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key request with " 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "invalid MIC"); 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO: should decrypt key data field if encryption was used; 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * even though MAC address KDE is not normally encrypted, 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * supplicant is allowed to encrypt it. 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == SMK_ERROR) { 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_smk_error(wpa_auth, sm, key); 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_info & WPA_KEY_INFO_ERROR) { 11071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_receive_error_report( 11081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_auth, sm, 11091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt !(key_info & WPA_KEY_INFO_KEY_TYPE)); 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_info & WPA_KEY_INFO_KEY_TYPE) { 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key Request for new " 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "4-Way Handshake"); 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_request_new_ptk(sm); 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (msg == SMK_M1) { 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_smk_m1(wpa_auth, sm, key); 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_data_length > 0 && 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_parse_kde_ies((const u8 *) (key + 1), 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_data_length, &kde) == 0 && 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.mac_addr) { 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key Request for GTK " 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "rekeying"); 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL); 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_rekey_gtk(wpa_auth, NULL); 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1131c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* Do not allow the same key replay counter to be reused. */ 1132c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_replay_counter_mark_invalid(sm->key_replay, 1133c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt key->replay_counter); 1134c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 1135c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (msg == PAIRWISE_2) { 1136c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 1137c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * Maintain a copy of the pending EAPOL-Key frames in 1138c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * case the EAPOL-Key frame was retransmitted. This is 1139c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * needed to allow EAPOL-Key msg 2/4 reply to another 1140c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * pending msg 1/4 to update the SNonce to work around 1141c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * unexpected supplicant behavior. 1142c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 1143c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt os_memcpy(sm->prev_key_replay, sm->key_replay, 1144c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sizeof(sm->key_replay)); 1145c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } else { 1146c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt os_memset(sm->prev_key_replay, 0, 1147c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sizeof(sm->prev_key_replay)); 1148c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 1149c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 1150c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 1151c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * Make sure old valid counters are not accepted anymore and 1152c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * do not get copied again. 1153c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 1154c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_replay_counter_mark_invalid(sm->key_replay, NULL); 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == SMK_M3) { 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_smk_m3(wpa_auth, sm, key); 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->last_rx_eapol_key); 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->last_rx_eapol_key = os_malloc(data_len); 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->last_rx_eapol_key == NULL) 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->last_rx_eapol_key, data, data_len); 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->last_rx_eapol_key_len = data_len; 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt sm->rx_eapol_key_secure = !!(key_info & WPA_KEY_INFO_SECURE); 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->EAPOLKeyReceived = TRUE; 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE); 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST); 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN); 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_step(sm); 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr, 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *gnonce, u8 *gtk, size_t gtk_len) 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 data[ETH_ALEN + WPA_NONCE_LEN + 8 + 16]; 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* GTK = PRF-X(GMK, "Group key expansion", 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AA || GNonce || Time || random data) 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The example described in the IEEE 802.11 standard uses only AA and 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * GNonce as inputs here. Add some more entropy since this derivation 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * is done only at the Authenticator and as such, does not need to be 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * exactly same. 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data, addr, ETH_ALEN); 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN); 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = data + ETH_ALEN + WPA_NONCE_LEN; 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_get_ntp_timestamp(pos); 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 8; 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(pos, 16) < 0) 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), gtk, gtk_len); 12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_IEEE80211W */ 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sha1_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), gtk, gtk_len) 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt < 0) 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx) 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_authenticator *wpa_auth = eloop_ctx; 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm = timeout_ctx; 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pending_1_of_4_timeout = 0; 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "EAPOL-Key timeout"); 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutEvt = TRUE; 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_step(sm); 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid __wpa_send_eapol(struct wpa_authenticator *wpa_auth, 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm, int key_info, 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *key_rsc, const u8 *nonce, 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *kde, size_t kde_len, 12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int keyidx, int encr, int force_version) 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee802_1x_hdr *hdr; 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *key; 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int alg; 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int key_data_len, pad_len = 0; 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *pos; 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int version, pairwise; 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = sizeof(struct ieee802_1x_hdr) + sizeof(struct wpa_eapol_key); 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (force_version) 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt version = force_version; 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (wpa_use_aes_cmac(sm)) 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt version = WPA_KEY_INFO_TYPE_AES_128_CMAC; 124761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt else if (sm->pairwise != WPA_CIPHER_TKIP) 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt version = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pairwise = key_info & WPA_KEY_INFO_KEY_TYPE; 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Send EAPOL(version=%d secure=%d mic=%d " 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ack=%d install=%d pairwise=%d kde_len=%lu keyidx=%d " 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "encr=%d)", 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt version, 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (key_info & WPA_KEY_INFO_SECURE) ? 1 : 0, 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (key_info & WPA_KEY_INFO_MIC) ? 1 : 0, 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (key_info & WPA_KEY_INFO_ACK) ? 1 : 0, 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (key_info & WPA_KEY_INFO_INSTALL) ? 1 : 0, 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pairwise, (unsigned long) kde_len, keyidx, encr); 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_data_len = kde_len; 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) { 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad_len = key_data_len % 8; 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pad_len) 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad_len = 8 - pad_len; 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_data_len += pad_len + 8; 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += key_data_len; 12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = os_zalloc(len); 12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr == NULL) 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->version = wpa_auth->conf.eapol_version; 12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->type = IEEE802_1X_TYPE_EAPOL_KEY; 12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->length = host_to_be16(len - sizeof(*hdr)); 12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = (struct wpa_eapol_key *) (hdr + 1); 12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->type = sm->wpa == WPA_VERSION_WPA2 ? 12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; 12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info |= version; 12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (encr && sm->wpa == WPA_VERSION_WPA2) 12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info |= WPA_KEY_INFO_ENCR_KEY_DATA; 12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa != WPA_VERSION_WPA2) 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info |= keyidx << WPA_KEY_INFO_KEY_INDEX_SHIFT; 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(key->key_info, key_info); 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt alg = pairwise ? sm->pairwise : wpa_auth->conf.wpa_group; 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (alg) { 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_CCMP: 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(key->key_length, 16); 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 129861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt case WPA_CIPHER_GCMP: 129961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt WPA_PUT_BE16(key->key_length, 16); 130061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_TKIP: 13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(key->key_length, 32); 13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_WEP40: 13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(key->key_length, 5); 13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_WEP104: 13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(key->key_length, 13); 13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_SMK_MESSAGE) 13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(key->key_length, 0); 13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: STSL: what to use as key_replay_counter? */ 13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = RSNA_MAX_EAPOL_RETRIES - 1; i > 0; i--) { 13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->key_replay[i].valid = sm->key_replay[i - 1].valid; 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->key_replay[i].counter, 13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->key_replay[i - 1].counter, 13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(sm->key_replay[0].counter, WPA_REPLAY_COUNTER_LEN); 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key->replay_counter, sm->key_replay[0].counter, 13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->key_replay[0].valid = TRUE; 13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nonce) 13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key->key_nonce, nonce, WPA_NONCE_LEN); 13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_rsc) 13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key->key_rsc, key_rsc, WPA_KEY_RSC_LEN); 13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde && !encr) { 13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key + 1, kde, kde_len); 13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(key->key_data_length, kde_len); 13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (encr && kde) { 13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_zalloc(key_data_len); 13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(hdr); 13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, kde, kde_len); 13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += kde_len; 13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pad_len) 13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 0xdd; 13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data", 13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf, key_data_len); 13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || 13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt version == WPA_KEY_INFO_TYPE_AES_128_CMAC) { 13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (aes_wrap(sm->PTK.kek, (key_data_len - 8) / 8, buf, 13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) (key + 1))) { 13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(hdr); 13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(key->key_data_length, key_data_len); 13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ek[32]; 13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key->key_iv, 13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group->Counter + WPA_NONCE_LEN - 16, 16); 13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(sm->group->Counter, WPA_NONCE_LEN); 13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ek, key->key_iv, 16); 13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ek + 16, sm->PTK.kek, 16); 13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key + 1, buf, key_data_len); 13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rc4_skip(ek, 32, 256, (u8 *) (key + 1), key_data_len); 13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(key->key_data_length, key_data_len); 13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_MIC) { 13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->PTK_valid) { 13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, 13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PTK not valid when sending EAPOL-Key " 13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "frame"); 13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(hdr); 13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_eapol_key_mic(sm->PTK.kck, version, (u8 *) hdr, len, 13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_mic); 13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, 13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1); 13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_send_eapol(wpa_auth, sm->addr, (u8 *) hdr, len, 13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pairwise_set); 13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(hdr); 13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_send_eapol(struct wpa_authenticator *wpa_auth, 13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm, int key_info, 13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *key_rsc, const u8 *nonce, 13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *kde, size_t kde_len, 13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int keyidx, int encr) 13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int timeout_ms; 14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE; 14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ctr; 14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len, 14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keyidx, encr, 0); 14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctr = pairwise ? sm->TimeoutCtr : sm->GTimeoutCtr; 14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ctr == 1 && wpa_auth->conf.tx_status) 14111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt timeout_ms = pairwise ? eapol_key_timeout_first : 14121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eapol_key_timeout_first_group; 14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeout_ms = eapol_key_timeout_subseq; 14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pairwise && ctr == 1 && !(key_info & WPA_KEY_INFO_MIC)) 14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pending_1_of_4_timeout = 1; 14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Use EAPOL-Key timeout of %u ms (retry " 14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "counter %d)", timeout_ms, ctr); 14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000, 14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_send_eapol_timeout, wpa_auth, sm); 14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_verify_key_mic(struct wpa_ptk *PTK, u8 *data, size_t data_len) 14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee802_1x_hdr *hdr; 14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *key; 14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info; 14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mic[16]; 14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data_len < sizeof(*hdr) + sizeof(*key)) 14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct ieee802_1x_hdr *) data; 14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = (struct wpa_eapol_key *) (hdr + 1); 14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = WPA_GET_BE16(key->key_info); 14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(mic, key->key_mic, 16); 14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(key->key_mic, 0, 16); 14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_eapol_key_mic(PTK->kck, key_info & WPA_KEY_INFO_TYPE_MASK, 14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data, data_len, key->key_mic) || 14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(mic, key->key_mic, 16) != 0) 14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key->key_mic, mic, 16); 14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_remove_ptk(struct wpa_state_machine *sm) 14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PTK_valid = FALSE; 14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&sm->PTK, 0, sizeof(sm->PTK)); 14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, NULL, 0); 14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pairwise_set = FALSE; 14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); 14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event) 14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int remove_ptk = 1; 14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "event %d notification", event); 14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (event) { 14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_AUTH: 14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_ASSOC: 14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_DEAUTH: 14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_DISASSOC: 14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->DeauthenticationRequest = TRUE; 14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_REAUTH: 14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_REAUTH_EAPOL: 14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->started) { 14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * When using WPS, we may end up here if the STA 14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * manages to re-associate without the previous STA 14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * entry getting removed. Consequently, we need to make 14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * sure that the WPA state machines gets initialized 14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * properly at this point. 14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA state machine had not been " 14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "started - initialize now"); 14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->started = 1; 14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->Init = TRUE; 14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_step(sm) == 1) 14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; /* should not really happen */ 14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->Init = FALSE; 14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->AuthenticationRequest = TRUE; 14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->GUpdateStationKeys) { 14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Reauthentication cancels the pending group key 15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * update for this STA. 15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group->GKeyDoneStations--; 15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GUpdateStationKeys = FALSE; 15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PtkGroupInit = TRUE; 15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ReAuthenticationRequest = TRUE; 15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_ASSOC_FT: 15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "FT: Retry PTK configuration " 15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "after association"); 15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ft_install_ptk(sm); 15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Using FT protocol, not WPA auth state machine */ 15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ft_completed = 1; 15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_IEEE80211R */ 15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ft_completed = 0; 15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->mgmt_frame_prot && event == WPA_AUTH) 15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt remove_ptk = 0; 15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (remove_ptk) { 15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PTK_valid = FALSE; 15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&sm->PTK, 0, sizeof(sm->PTK)); 15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (event != WPA_REAUTH_EAPOL) 15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_remove_ptk(sm); 15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_sm_step(sm); 15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum wpa_alg wpa_alg_enum(int alg) 15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (alg) { 15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_CCMP: 15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_ALG_CCMP; 154861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt case WPA_CIPHER_GCMP: 154961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return WPA_ALG_GCMP; 15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_TKIP: 15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_ALG_TKIP; 15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_WEP104: 15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_WEP40: 15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_ALG_WEP; 15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_ALG_NONE; 15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, INITIALIZE) 15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, INITIALIZE, wpa_ptk); 15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->Init) { 15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Init flag is not cleared here, so avoid busy 15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * loop by claiming nothing changed. */ 15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->changed = FALSE; 15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->keycount = 0; 15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->GUpdateStationKeys) 15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group->GKeyDoneStations--; 15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GUpdateStationKeys = FALSE; 15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA) 15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PInitAKeys = FALSE; 15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (1 /* Unicast cipher supported AND (ESS OR ((IBSS or WDS) and 15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Local AA > Remote AA)) */) { 15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->Pair = TRUE; 15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 0); 15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_remove_ptk(sm); 15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 0); 15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutCtr = 0; 15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { 15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, 15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_EAPOL_authorized, 0); 15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, DISCONNECT) 15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, DISCONNECT, wpa_ptk); 15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->Disconnect = FALSE; 15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sta_disconnect(sm->wpa_auth, sm->addr); 15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, DISCONNECTED) 16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, DISCONNECTED, wpa_ptk); 16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->DeauthenticationRequest = FALSE; 16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, AUTHENTICATION) 16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, AUTHENTICATION, wpa_ptk); 16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&sm->PTK, 0, sizeof(sm->PTK)); 16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PTK_valid = FALSE; 16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portControl_Auto, 16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1); 16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 1); 16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->AuthenticationRequest = FALSE; 16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1618c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic void wpa_group_ensure_init(struct wpa_authenticator *wpa_auth, 1619c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct wpa_group *group) 16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1621c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (group->first_sta_seen) 1622c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return; 16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * System has run bit further than at the time hostapd was started 16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * potentially very early during boot up. This provides better chances 16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * of collecting more randomness on embedded systems. Re-initialize the 16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * GMK and Counter here to improve their strength if there was not 16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * enough entropy available immediately after system startup. 16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Re-initialize GMK/Counter on first " 16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "station"); 16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_pool_ready() != 1) { 16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPA: Not enough entropy in random pool " 16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "to proceed - reject first 4-way handshake"); 16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->reject_4way_hs_for_entropy = TRUE; 1636c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } else { 1637c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt group->first_sta_seen = TRUE; 1638c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt group->reject_4way_hs_for_entropy = FALSE; 16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1640c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_init_gmk_and_counter(wpa_auth, group); 16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_gtk_update(wpa_auth, group); 16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_config_group_keys(wpa_auth, group); 16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, AUTHENTICATION2) 16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, AUTHENTICATION2, wpa_ptk); 16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1651c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_group_ensure_init(sm->wpa_auth, sm->group); 16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 165304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* 165404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * Definition of ANonce selection in IEEE Std 802.11i-2004 is somewhat 165504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * ambiguous. The Authenticator state machine uses a counter that is 165604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * incremented by one for each 4-way handshake. However, the security 165704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * analysis of 4-way handshake points out that unpredictable nonces 165804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * help in preventing precomputation attacks. Instead of the state 165904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * machine definition, use an unpredictable nonce value here to provide 166004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * stronger protection against potential precomputation attacks. 166104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt */ 166204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) { 166304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_ERROR, "WPA: Failed to get random data for " 166404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "ANonce."); 166504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_sta_disconnect(sm->wpa_auth, sm->addr); 166604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 166704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Assign ANonce", sm->ANonce, 16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_NONCE_LEN); 16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ReAuthenticationRequest = FALSE; 16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* IEEE 802.11i does not clear TimeoutCtr here, but this is more 16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * logical place than INITIALIZE since AUTHENTICATION2 can be 16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * re-entered on ReAuthenticationRequest without going through 16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * INITIALIZE. */ 16758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutCtr = 0; 16768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, INITPMK) 16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 msk[2 * PMK_LEN]; 16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len = 2 * PMK_LEN; 16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, INITPMK, wpa_ptk); 16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->xxkey_len = 0; 16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pmksa) { 16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: PMK from PMKSA cache"); 16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->PMK, sm->pmksa->pmk, PMK_LEN); 16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (wpa_auth_get_msk(sm->wpa_auth, sm->addr, msk, &len) == 0) { 16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: PMK from EAPOL state machine " 16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(len=%lu)", (unsigned long) len); 16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->PMK, msk, PMK_LEN); 16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len >= 2 * PMK_LEN) { 16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->xxkey, msk + PMK_LEN, PMK_LEN); 16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->xxkey_len = PMK_LEN; 16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Could not get PMK"); 17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->req_replay_counter_used = 0; 17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* IEEE 802.11i does not set keyRun to FALSE, but not doing this 17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * will break reauthentication since EAPOL state machines may not be 17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * get into AUTHENTICATING state that clears keyRun before WPA state 17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * machine enters AUTHENTICATION2 state and goes immediately to INITPMK 17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * state and takes PMK from the previously used AAA Key. This will 17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eventually fail in 4-Way Handshake because Supplicant uses PMK 17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * derived from the new AAA Key. Setting keyRun = FALSE here seems to 17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * be good workaround for this issue. */ 17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun, 0); 17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, INITPSK) 17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *psk; 17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk); 17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, NULL); 17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (psk) { 17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->PMK, psk, PMK_LEN); 17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->xxkey, psk, PMK_LEN); 17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->xxkey_len = PMK_LEN; 17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->req_replay_counter_used = 0; 17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, PTKSTART) 17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 buf[2 + RSN_SELECTOR_LEN + PMKID_LEN], *pmkid = NULL; 17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t pmkid_len = 0; 17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, PTKSTART, wpa_ptk); 17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PTKRequest = FALSE; 17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutEvt = FALSE; 17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutCtr++; 17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->TimeoutCtr > (int) dot11RSNAConfigPairwiseUpdateCount) { 17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No point in sending the EAPOL-Key - we will disconnect 17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * immediately following this. */ 17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "sending 1/4 msg of 4-Way Handshake"); 17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO: Could add PMKID even with WPA2-PSK, but only if there is only 17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * one possible PSK for this STA. 17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA2 && 17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt)) { 17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmkid = buf; 17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN; 17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmkid[0] = WLAN_EID_VENDOR_SPECIFIC; 17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN; 17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(&pmkid[2], RSN_KEY_DATA_PMKID); 17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pmksa) 17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN], 17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmksa->pmkid, PMKID_LEN); 17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Calculate PMKID since no PMKSA cache entry was 17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * available with pre-calculated PMKID. 17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_pmkid(sm->PMK, PMK_LEN, sm->wpa_auth->addr, 17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->addr, &pmkid[2 + RSN_SELECTOR_LEN], 17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_key_mgmt_sha256(sm->wpa_key_mgmt)); 17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_send_eapol(sm->wpa_auth, sm, 17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL, 17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ANonce, pmkid, pmkid_len, 0, 0); 17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *pmk, 17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ptk *ptk) 17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 178561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t ptk_len = sm->pairwise != WPA_CIPHER_TKIP ? 48 : 64; 17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) 17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth_derive_ptk_ft(sm, pmk, ptk, ptk_len); 17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_pmk_to_ptk(pmk, PMK_LEN, "Pairwise key expansion", 17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_auth->addr, sm->addr, sm->ANonce, sm->SNonce, 17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) ptk, ptk_len, 17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_key_mgmt_sha256(sm->wpa_key_mgmt)); 17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, PTKCALCNEGOTIATING) 18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ptk PTK; 18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ok = 0; 18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pmk = NULL; 18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk); 18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->EAPOLKeyReceived = FALSE; 1808c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sm->update_snonce = FALSE; 18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* WPA with IEEE 802.1X: use the derived PMK from EAP 18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA-PSK: iterate through possible PSKs and select the one matching 18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the packet */ 18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (;;) { 18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { 18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, pmk); 18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmk == NULL) 18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmk = sm->PMK; 18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_derive_ptk(sm, pmk, &PTK); 18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_verify_key_mic(&PTK, sm->last_rx_eapol_key, 18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->last_rx_eapol_key_len) == 0) { 18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ok = 1; 18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) 18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ok) { 18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "invalid MIC in msg 2/4 of 4-Way Handshake"); 18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { 18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Verify that PMKR1Name from EAPOL-Key message 2/4 matches 18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * with the value we derived. 18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(sm->sup_pmk_r1_name, sm->pmk_r1_name, 18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PMK_NAME_LEN) != 0) { 18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PMKR1Name mismatch in FT 4-way " 18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "handshake"); 18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from " 18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Supplicant", 18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->sup_pmk_r1_name, WPA_PMK_NAME_LEN); 18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name", 18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmk_r1_name, WPA_PMK_NAME_LEN); 18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pending_1_of_4_timeout = 0; 18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm); 18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { 18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* PSK may have changed from the previous choice, so update 18658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * state machine data based on whatever PSK was selected here. 18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->PMK, pmk, PMK_LEN); 18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->MICVerified = TRUE; 18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&sm->PTK, &PTK, sizeof(PTK)); 18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PTK_valid = TRUE; 18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, PTKCALCNEGOTIATING2) 18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING2, wpa_ptk); 18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutCtr = 0; 18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee80211w_kde_len(struct wpa_state_machine *sm) 18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->mgmt_frame_prot) { 18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 2 + RSN_SELECTOR_LEN + sizeof(struct wpa_igtk_kde); 18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) 18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_igtk_kde igtk; 18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *gsm = sm->group; 19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->mgmt_frame_prot) 19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt igtk.keyid[0] = gsm->GN_igtk; 19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt igtk.keyid[1] = 0; 19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE || 19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, igtk.pn) < 0) 19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(igtk.pn, 0, sizeof(igtk.pn)); 19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN); 191061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->wpa_auth->conf.disable_gtk) { 191161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* 191261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Provide unique random IGTK to each STA to prevent use of 191361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * IGTK in the BSS. 191461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 191561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (random_get_bytes(igtk.igtk, WPA_IGTK_LEN) < 0) 191661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return pos; 191761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK, 19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (const u8 *) &igtk, sizeof(igtk), NULL, 0); 19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_IEEE80211W */ 19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee80211w_kde_len(struct wpa_state_machine *sm) 19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) 19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, PTKINITNEGOTIATING) 19418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 194261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos, dummy_gtk[32]; 19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t gtk_len, kde_len; 19448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *gsm = sm->group; 19458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *wpa_ie; 19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int wpa_ie_len, secure, keyidx, encr = 0; 19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk); 19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutEvt = FALSE; 19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutCtr++; 19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->TimeoutCtr > (int) dot11RSNAConfigPairwiseUpdateCount) { 19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No point in sending the EAPOL-Key - we will disconnect 19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * immediately following this. */ 19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE], 19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GTK[GN], IGTK, [FTIE], [TIE * 2]) 19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(rsc, 0, WPA_KEY_RSC_LEN); 19628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc); 19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */ 19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ie = sm->wpa_auth->wpa_ie; 19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ie_len = sm->wpa_auth->wpa_ie_len; 19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA && 19678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) && 19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ie_len > wpa_ie[1] + 2 && wpa_ie[0] == WLAN_EID_RSN) { 19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* WPA-only STA, remove RSN IE */ 19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ie = wpa_ie + wpa_ie[1] + 2; 19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ie_len = wpa_ie[1] + 2; 19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "sending 3/4 msg of 4-Way Handshake"); 19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA2) { 19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* WPA2 send GTK in the 4-way handshake */ 19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt secure = 1; 19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gtk = gsm->GTK[gsm->GN - 1]; 19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gtk_len = gsm->GTK_len; 198061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->wpa_auth->conf.disable_gtk) { 198161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* 198261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Provide unique random GTK to each STA to prevent use 198361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * of GTK in the BSS. 198461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 198561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (random_get_bytes(dummy_gtk, gtk_len) < 0) 198661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 198761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gtk = dummy_gtk; 198861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keyidx = gsm->GN; 19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _rsc = rsc; 19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encr = 1; 19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* WPA does not include GTK in msg 3/4 */ 19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt secure = 0; 19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gtk = NULL; 19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gtk_len = 0; 19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keyidx = 0; 19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _rsc = NULL; 19991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (sm->rx_eapol_key_secure) { 20001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 20011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * It looks like Windows 7 supplicant tries to use 20021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Secure bit in msg 2/4 after having reported Michael 20031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * MIC failure and it then rejects the 4-way handshake 20041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * if msg 3/4 does not set Secure bit. Work around this 20051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * by setting the Secure bit here even in the case of 20061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * WPA if the supplicant used it first. 20071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 20081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 20091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "STA used Secure bit in WPA msg 2/4 - " 20101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "set Secure for 3/4 as workaround"); 20111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt secure = 1; 20121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len = wpa_ie_len + ieee80211w_kde_len(sm); 20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gtk) 20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len; 20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 20198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { 20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */ 20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len += 300; /* FTIE + 2 * TIE */ 20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde = os_malloc(kde_len); 20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde == NULL) 20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = kde; 20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, wpa_ie, wpa_ie_len); 20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += wpa_ie_len; 20318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { 20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res = wpa_insert_pmkid(kde, pos - kde, sm->pmk_r1_name); 20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "FT: Failed to insert " 20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PMKR1Name into RSN IE in EAPOL-Key data"); 20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(kde); 20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += res; 20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gtk) { 20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hdr[2]; 20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr[0] = keyidx & 0x03; 20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr[1] = 0; 20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, 20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gtk, gtk_len); 20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = ieee80211w_kde_add(sm, pos); 20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { 20548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_auth_config *conf; 20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf = &sm->wpa_auth->conf; 20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wpa_write_ftie(conf, conf->r0_key_holder, 20598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf->r0_key_holder_len, 20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, NULL, pos, kde + kde_len - pos, 20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0); 20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 20638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE " 20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "into EAPOL-Key Key Data"); 20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(kde); 20668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 20678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += res; 20698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TIE[ReassociationDeadline] (TU) */ 20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = WLAN_EID_TIMEOUT_INTERVAL; 20728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 5; 20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE; 20748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE32(pos, conf->reassociation_deadline); 20758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 4; 20768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TIE[KeyLifetime] (seconds) */ 20788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = WLAN_EID_TIMEOUT_INTERVAL; 20798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 5; 20808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = WLAN_TIMEOUT_KEY_LIFETIME; 20818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE32(pos, conf->r0_key_lifetime * 60); 20828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 4; 20838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_send_eapol(sm->wpa_auth, sm, 20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (secure ? WPA_KEY_INFO_SECURE : 0) | WPA_KEY_INFO_MIC | 20888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL | 20898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_KEY_TYPE, 20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _rsc, sm->ANonce, kde, pos - kde, keyidx, encr); 20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(kde); 20928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, PTKINITDONE) 20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk); 20988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->EAPOLKeyReceived = FALSE; 20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->Pair) { 21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wpa_alg alg; 21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int klen; 21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pairwise == WPA_CIPHER_TKIP) { 21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt alg = WPA_ALG_TKIP; 21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt klen = 32; 210561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else if (sm->pairwise == WPA_CIPHER_GCMP) { 210661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt alg = WPA_ALG_GCMP; 210761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt klen = 16; 21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt alg = WPA_ALG_CCMP; 21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt klen = 16; 21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, 21138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PTK.tk1, klen)) { 21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sta_disconnect(sm->wpa_auth, sm->addr); 21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ 21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pairwise_set = TRUE; 21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_auth->conf.wpa_ptk_rekey) { 21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); 21228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(sm->wpa_auth->conf. 21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ptk_rekey, 0, wpa_rekey_ptk, 21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_auth, sm); 21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { 21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, 21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_EAPOL_authorized, 1); 21308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (0 /* IBSS == TRUE */) { 21348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->keycount++; 21358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->keycount == 2) { 21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, 21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_EAPOL_portValid, 1); 21388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1); 21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyAvailable, 0); 21448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyDone, 1); 21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA) 21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PInitAKeys = TRUE; 21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->has_GTK = TRUE; 21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, 21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pairwise key handshake completed (%s)", 21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN"); 21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ft_push_pmk_r1(sm->wpa_auth, sm->addr); 21558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 21568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 21578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STEP(WPA_PTK) 21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_authenticator *wpa_auth = sm->wpa_auth; 21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->Init) 21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, INITIALIZE); 21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->Disconnect 21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* || FIX: dot11RSNAConfigSALifetime timeout */) { 21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, 21688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA_PTK: sm->Disconnect"); 21698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, DISCONNECT); 21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->DeauthenticationRequest) 21728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, DISCONNECTED); 21738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->AuthenticationRequest) 21748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, AUTHENTICATION); 21758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->ReAuthenticationRequest) 21768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, AUTHENTICATION2); 21778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->PTKRequest) 21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKSTART); 21798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else switch (sm->wpa_ptk_state) { 21808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_INITIALIZE: 21818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_DISCONNECT: 21838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, DISCONNECTED); 21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_DISCONNECTED: 21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, INITIALIZE); 21878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_AUTHENTICATION: 21898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, AUTHENTICATION2); 21908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_AUTHENTICATION2: 21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) && 21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_get_eapol(sm->wpa_auth, sm->addr, 21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_EAPOL_keyRun) > 0) 21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, INITPMK); 21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) 21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: && 802.1X::keyRun */) 21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, INITPSK); 21998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_INITPMK: 22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_get_eapol(sm->wpa_auth, sm->addr, 22028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_EAPOL_keyAvailable) > 0) 22038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKSTART); 22048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNA4WayHandshakeFailures++; 22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, 22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "INITPMK - keyAvailable = false"); 22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, DISCONNECT); 22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_INITPSK: 22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_get_psk(sm->wpa_auth, sm->addr, NULL)) 22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKSTART); 22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 22158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, 22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "no PSK configured for the STA"); 22178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNA4WayHandshakeFailures++; 22188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, DISCONNECT); 22198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 22218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_PTKSTART: 22228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && 22238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->EAPOLKeyPairwise) 22248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); 22258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->TimeoutCtr > 22268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) dot11RSNAConfigPairwiseUpdateCount) { 22278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNA4WayHandshakeFailures++; 22288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 22298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PTKSTART: Retry limit %d reached", 22308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dot11RSNAConfigPairwiseUpdateCount); 22318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, DISCONNECT); 22328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (sm->TimeoutEvt) 22338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKSTART); 22348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 22358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_PTKCALCNEGOTIATING: 22368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->MICVerified) 22378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING2); 22388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && 22398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->EAPOLKeyPairwise) 22408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); 22418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->TimeoutEvt) 22428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKSTART); 22438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 22448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_PTKCALCNEGOTIATING2: 22458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKINITNEGOTIATING); 22468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 22478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_PTKINITNEGOTIATING: 2248c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (sm->update_snonce) 2249c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); 2250c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && 2251c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sm->EAPOLKeyPairwise && sm->MICVerified) 22528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKINITDONE); 22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->TimeoutCtr > 22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) dot11RSNAConfigPairwiseUpdateCount) { 22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNA4WayHandshakeFailures++; 22568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 22578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PTKINITNEGOTIATING: Retry limit %d " 22588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "reached", 22598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dot11RSNAConfigPairwiseUpdateCount); 22608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, DISCONNECT); 22618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (sm->TimeoutEvt) 22628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKINITNEGOTIATING); 22638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 22648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_PTKINITDONE: 22658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 22668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 22688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22708d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK_GROUP, IDLE) 22718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 22728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK_GROUP, IDLE, wpa_ptk_group); 22738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->Init) { 22748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Init flag is not cleared here, so avoid busy 22758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * loop by claiming nothing changed. */ 22768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->changed = FALSE; 22778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GTimeoutCtr = 0; 22798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22828d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) 22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 22848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rsc[WPA_KEY_RSC_LEN]; 22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *gsm = sm->group; 22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *kde, *pos, hdr[2]; 22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t kde_len; 228861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 *gtk, dummy_gtk[32]; 22898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group); 22918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GTimeoutCtr++; 22938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->GTimeoutCtr > (int) dot11RSNAConfigGroupUpdateCount) { 22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No point in sending the EAPOL-Key - we will disconnect 22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * immediately following this. */ 22968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA) 23008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PInitAKeys = FALSE; 23018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutEvt = FALSE; 23028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */ 23038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(rsc, 0, WPA_KEY_RSC_LEN); 23048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gsm->wpa_group_state == WPA_GROUP_SETKEYSDONE) 23058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc); 23068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 23078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "sending 1/2 msg of Group Key Handshake"); 23088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 230961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gtk = gsm->GTK[gsm->GN - 1]; 231061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->wpa_auth->conf.disable_gtk) { 231161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* 231261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Provide unique random GTK to each STA to prevent use 231361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * of GTK in the BSS. 231461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 231561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (random_get_bytes(dummy_gtk, gsm->GTK_len) < 0) 231661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 231761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gtk = dummy_gtk; 231861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 23198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA2) { 23208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len + 23218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee80211w_kde_len(sm); 23228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde = os_malloc(kde_len); 23238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde == NULL) 23248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 23258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = kde; 23278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr[0] = gsm->GN & 0x03; 23288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr[1] = 0; 23298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, 233061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gtk, gsm->GTK_len); 23318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = ieee80211w_kde_add(sm, pos); 23328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 233361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt kde = gtk; 23348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = kde + gsm->GTK_len; 23358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_send_eapol(sm->wpa_auth, sm, 23388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC | 23398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_ACK | 23408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0), 23418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsc, gsm->GNonce, kde, pos - kde, gsm->GN, 1); 23428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA2) 23438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(kde); 23448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23478d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED) 23488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK_GROUP, REKEYESTABLISHED, wpa_ptk_group); 23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->EAPOLKeyReceived = FALSE; 23518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->GUpdateStationKeys) 23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group->GKeyDoneStations--; 23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GUpdateStationKeys = FALSE; 23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GTimeoutCtr = 0; 23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */ 23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, 23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "group key handshake completed (%s)", 23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN"); 23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->has_GTK = TRUE; 23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK_GROUP, KEYERROR) 23648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK_GROUP, KEYERROR, wpa_ptk_group); 23668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->GUpdateStationKeys) 23678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group->GKeyDoneStations--; 23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GUpdateStationKeys = FALSE; 23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->Disconnect = TRUE; 23708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23738d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STEP(WPA_PTK_GROUP) 23748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->Init || sm->PtkGroupInit) { 23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK_GROUP, IDLE); 23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PtkGroupInit = FALSE; 23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else switch (sm->wpa_ptk_group_state) { 23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_GROUP_IDLE: 23808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->GUpdateStationKeys || 23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (sm->wpa == WPA_VERSION_WPA && sm->PInitAKeys)) 23828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING); 23838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_GROUP_REKEYNEGOTIATING: 23858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && 23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !sm->EAPOLKeyPairwise && sm->MICVerified) 23878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK_GROUP, REKEYESTABLISHED); 23888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->GTimeoutCtr > 23898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) dot11RSNAConfigGroupUpdateCount) 23908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK_GROUP, KEYERROR); 23918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->TimeoutEvt) 23928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING); 23938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_GROUP_KEYERROR: 23958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK_GROUP, IDLE); 23968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_GROUP_REKEYESTABLISHED: 23988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK_GROUP, IDLE); 23998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 24008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 24028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_gtk_update(struct wpa_authenticator *wpa_auth, 24058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group) 24068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 24078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 24088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); 24108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(group->Counter, WPA_NONCE_LEN); 24118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_gmk_to_gtk(group->GMK, "Group key expansion", 24128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->addr, group->GNonce, 24138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTK[group->GN - 1], group->GTK_len) < 0) 24148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 24158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "GTK", 24168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTK[group->GN - 1], group->GTK_len); 24178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 24198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) { 24208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); 24218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(group->Counter, WPA_NONCE_LEN); 24228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion", 24238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->addr, group->GNonce, 24248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->IGTK[group->GN_igtk - 4], 24258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_IGTK_LEN) < 0) 24268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 24278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IGTK", 24288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->IGTK[group->GN_igtk - 4], WPA_IGTK_LEN); 24298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 24318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 24338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 24348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth, 24378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group) 24388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 24398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " 24408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "GTK_INIT (VLAN-ID %d)", group->vlan_id); 24418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->changed = FALSE; /* GInit is not cleared here; avoid loop */ 24428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->wpa_group_state = WPA_GROUP_GTK_INIT; 24438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* GTK[0..N] = 0 */ 24458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(group->GTK, 0, sizeof(group->GTK)); 24468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GN = 1; 24478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GM = 2; 24488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 24498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GN_igtk = 4; 24508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GM_igtk = 5; 24518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 24528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* GTK[GN] = CalcGTK() */ 24538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_gtk_update(wpa_auth, group); 24548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 24558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx) 24588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 245961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (ctx != NULL && ctx != sm->group) 246061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 246161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 24628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) { 24638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 24648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Not in PTKINITDONE; skip Group Key update"); 24658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GUpdateStationKeys = FALSE; 24668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 24678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->GUpdateStationKeys) { 24698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 24708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This should not really happen, so add a debug log entry. 24718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Since we clear the GKeyDoneStations before the loop, the 24728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * station needs to be counted here anyway. 24738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 24748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 24758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "GUpdateStationKeys was already set when " 24768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "marking station for GTK rekeying"); 24778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 247961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_IEEE80211V 248061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* Do not rekey GTK/IGTK when STA is in wnmsleep */ 248161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->is_wnmsleep) 248261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 248361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_IEEE80211V */ 248461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 24858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group->GKeyDoneStations++; 24868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GUpdateStationKeys = TRUE; 24878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_step(sm); 24898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 24908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 24918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 249361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_IEEE80211V 249461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt/* update GTK when exiting wnmsleep mode */ 249561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm) 249661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 249761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->is_wnmsleep) 249861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 249961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 250061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_group_update_sta(sm, NULL); 250161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 250261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 250361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 250461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag) 250561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 250661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sm->is_wnmsleep = !!flag; 250761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 250861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 250961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 251061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos) 251161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 251261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 *subelem; 251361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_group *gsm = sm->group; 251461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t subelem_len, pad_len; 251561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *key; 251661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t key_len; 251761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 keybuf[32]; 251861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 251961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* GTK subslement */ 252061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt key_len = gsm->GTK_len; 252161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (key_len > sizeof(keybuf)) 252261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 252361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 252461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* 252561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Pad key for AES Key Wrap if it is not multiple of 8 bytes or is less 252661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * than 16 bytes. 252761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 252861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pad_len = key_len % 8; 252961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (pad_len) 253061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pad_len = 8 - pad_len; 253161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (key_len + pad_len < 16) 253261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pad_len += 8; 253361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (pad_len) { 253461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_memcpy(keybuf, gsm->GTK[gsm->GN - 1], key_len); 253561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_memset(keybuf + key_len, 0, pad_len); 253661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt keybuf[key_len] = 0xdd; 253761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt key_len += pad_len; 253861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt key = keybuf; 253961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else 254061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt key = gsm->GTK[gsm->GN - 1]; 254161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 254261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* 254361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] | 254461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Key[5..32] | 8 padding. 254561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 254661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt subelem_len = 13 + key_len + 8; 254761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt subelem = os_zalloc(subelem_len); 254861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (subelem == NULL) 254961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 255061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 255161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt subelem[0] = WNM_SLEEP_SUBELEM_GTK; 255261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt subelem[1] = 11 + key_len + 8; 255361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* Key ID in B0-B1 of Key Info */ 255461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt WPA_PUT_LE16(&subelem[2], gsm->GN & 0x03); 255561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt subelem[4] = gsm->GTK_len; 255661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, subelem + 5) != 0) 255761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt { 255861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_free(subelem); 255961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 256061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 256161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (aes_wrap(sm->PTK.kek, key_len / 8, key, subelem + 13)) { 256261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_free(subelem); 256361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 256461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 256561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 256661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_memcpy(pos, subelem, subelem_len); 256761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 256861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "Plaintext GTK", 256961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gsm->GTK[gsm->GN - 1], gsm->GTK_len); 257061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_free(subelem); 257161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 257261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return subelem_len; 257361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 257461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 257561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 257661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_IEEE80211W 257761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos) 257861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 257961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 *subelem, *ptr; 258061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_group *gsm = sm->group; 258161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t subelem_len; 258261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 258361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* IGTK subelement 258461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | 258561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Key[16] | 8 padding */ 258661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt subelem_len = 1 + 1 + 2 + 6 + WPA_IGTK_LEN + 8; 258761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt subelem = os_zalloc(subelem_len); 258861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (subelem == NULL) 258961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 259061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 259161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ptr = subelem; 259261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt *ptr++ = WNM_SLEEP_SUBELEM_IGTK; 259361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt *ptr++ = subelem_len - 2; 259461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt WPA_PUT_LE16(ptr, gsm->GN_igtk); 259561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ptr += 2; 259661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, ptr) != 0) { 259761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_free(subelem); 259861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 259961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 260061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ptr += 6; 260161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (aes_wrap(sm->PTK.kek, WPA_IGTK_LEN / 8, 260261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gsm->IGTK[gsm->GN_igtk - 4], ptr)) { 260361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_free(subelem); 260461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 260561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 260661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 260761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_memcpy(pos, subelem, subelem_len); 260861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 260961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "Plaintext IGTK", 261061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN); 261161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_free(subelem); 261261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 261361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return subelem_len; 261461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 261561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 261661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_IEEE80211V */ 261761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 261861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 26198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_group_setkeys(struct wpa_authenticator *wpa_auth, 26208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group) 26218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tmp; 26238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " 26258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SETKEYS (VLAN-ID %d)", group->vlan_id); 26268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->changed = TRUE; 26278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->wpa_group_state = WPA_GROUP_SETKEYS; 26288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTKReKey = FALSE; 26298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = group->GM; 26308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GM = group->GN; 26318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GN = tmp; 26328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 26338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = group->GM_igtk; 26348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GM_igtk = group->GN_igtk; 26358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GN_igtk = tmp; 26368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 26378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* "GKeyDoneStations = GNoStations" is done in more robust way by 26388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * counting the STAs that are marked with GUpdateStationKeys instead of 26398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * including all STAs that could be in not-yet-completed state. */ 26408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_gtk_update(wpa_auth, group); 26418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group->GKeyDoneStations) { 26438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "wpa_group_setkeys: Unexpected " 26448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "GKeyDoneStations=%d when starting new GTK rekey", 26458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GKeyDoneStations); 26468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GKeyDoneStations = 0; 26478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 264861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_auth_for_each_sta(wpa_auth, wpa_group_update_sta, group); 26498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "wpa_group_setkeys: GKeyDoneStations=%d", 26508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GKeyDoneStations); 26518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth, 26558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group) 26568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 26588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_set_key(wpa_auth, group->vlan_id, 26608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_alg_enum(wpa_auth->conf.wpa_group), 26618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt broadcast_ether_addr, group->GN, 26628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTK[group->GN - 1], group->GTK_len) < 0) 26638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 26648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 26668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION && 26678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_key(wpa_auth, group->vlan_id, WPA_ALG_IGTK, 26688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt broadcast_ether_addr, group->GN_igtk, 26698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->IGTK[group->GN_igtk - 4], 26708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_IGTK_LEN) < 0) 26718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 26728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 26738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 26758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth, 26798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group) 26808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " 26828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SETKEYSDONE (VLAN-ID %d)", group->vlan_id); 26838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->changed = TRUE; 26848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->wpa_group_state = WPA_GROUP_SETKEYSDONE; 26858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_group_config_group_keys(wpa_auth, group) < 0) 26878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 26888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 26908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_group_sm_step(struct wpa_authenticator *wpa_auth, 26948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group) 26958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group->GInit) { 26978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_gtk_init(wpa_auth, group); 26988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (group->wpa_group_state == WPA_GROUP_GTK_INIT && 26998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTKAuthenticator) { 27008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_setkeysdone(wpa_auth, group); 27018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (group->wpa_group_state == WPA_GROUP_SETKEYSDONE && 27028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTKReKey) { 27038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_setkeys(wpa_auth, group); 27048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (group->wpa_group_state == WPA_GROUP_SETKEYS) { 27058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group->GKeyDoneStations == 0) 27068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_setkeysdone(wpa_auth, group); 27078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (group->GTKReKey) 27088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_setkeys(wpa_auth, group); 27098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 27108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 27118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_sm_step(struct wpa_state_machine *sm) 27148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 27158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 27168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 27178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->in_step_loop) { 27198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* This should not happen, but if it does, make sure we do not 27208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * end up freeing the state machine too early by exiting the 27218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * recursive call. */ 27228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "WPA: wpa_sm_step() called recursively"); 27238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 27248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 27258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->in_step_loop = 1; 27278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt do { 27288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pending_deinit) 27298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 27308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->changed = FALSE; 27328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_auth->group->changed = FALSE; 27338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_STEP_RUN(WPA_PTK); 27358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pending_deinit) 27368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 27378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_STEP_RUN(WPA_PTK_GROUP); 27388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pending_deinit) 27398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 27408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_sm_step(sm->wpa_auth, sm->group); 27418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } while (sm->changed || sm->wpa_auth->group->changed); 27428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->in_step_loop = 0; 27438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pending_deinit) { 27458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Completing pending STA state " 27468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "machine deinit for " MACSTR, MAC2STR(sm->addr)); 27478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_free_sta_sm(sm); 27488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 27498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 27508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 27518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 27528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx) 27558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 27568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm = eloop_ctx; 27578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_step(sm); 27588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 27598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_auth_sm_notify(struct wpa_state_machine *sm) 27628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 27638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 27648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 27658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL); 27668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 27678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_gtk_rekey(struct wpa_authenticator *wpa_auth) 27708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 27718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tmp, i; 27728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group; 27738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL) 27758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 27768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = wpa_auth->group; 27788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < 2; i++) { 27808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = group->GM; 27818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GM = group->GN; 27828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GN = tmp; 27838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 27848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = group->GM_igtk; 27858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GM_igtk = group->GN_igtk; 27868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GN_igtk = tmp; 27878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 27888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_gtk_update(wpa_auth, group); 27891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_group_config_group_keys(wpa_auth, group); 27908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 27918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 27928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * wpa_bool_txt(int bool) 27958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 27968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return bool ? "TRUE" : "FALSE"; 27978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 27988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_cipher_bits(int cipher) 28018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 28028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (cipher) { 28038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_CCMP: 28048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 128; 280561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt case WPA_CIPHER_GCMP: 280661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 128; 28078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_TKIP: 28088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 256; 28098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_WEP104: 28108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 104; 28118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_WEP40: 28128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 40; 28138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 28148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 28158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 28168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 28178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RSN_SUITE "%02x-%02x-%02x-%d" 28208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RSN_SUITE_ARG(s) \ 28218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff 28228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen) 28248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 28258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int len = 0, ret; 28268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char pmkid_txt[PMKID_LEN * 2 + 1]; 28278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_RSN_PREAUTH 28288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const int preauth = 1; 28298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_RSN_PREAUTH */ 28308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const int preauth = 0; 28318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_RSN_PREAUTH */ 28328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL) 28348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 28358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, 28378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAOptionImplemented=TRUE\n" 28388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAPreauthenticationImplemented=%s\n" 28398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAEnabled=%s\n" 28408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAPreauthenticationEnabled=%s\n", 28418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_bool_txt(preauth), 28428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_bool_txt(wpa_auth->conf.wpa & WPA_PROTO_RSN), 28438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_bool_txt(wpa_auth->conf.rsn_preauth)); 28448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || (size_t) ret >= buflen - len) 28458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 28468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 28478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt), 28498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNAPMKIDUsed, PMKID_LEN); 28508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf( 28528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf + len, buflen - len, 28538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigVersion=%u\n" 28548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigPairwiseKeysSupported=9999\n" 28558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: dot11RSNAConfigGroupCipher */ 28568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: dot11RSNAConfigGroupRekeyMethod */ 28578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: dot11RSNAConfigGroupRekeyTime */ 28588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: dot11RSNAConfigGroupRekeyPackets */ 28598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigGroupRekeyStrict=%u\n" 28608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigGroupUpdateCount=%u\n" 28618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigPairwiseUpdateCount=%u\n" 28628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigGroupCipherSize=%u\n" 28638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigPMKLifetime=%u\n" 28648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigPMKReauthThreshold=%u\n" 28658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigNumberOfPTKSAReplayCounters=0\n" 28668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigSATimeout=%u\n" 28678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n" 28688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n" 28698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n" 28708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAPMKIDUsed=%s\n" 28718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n" 28728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n" 28738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n" 28748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNATKIPCounterMeasuresInvoked=%u\n" 28758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNA4WayHandshakeFailures=%u\n" 28768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n", 28778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_VERSION, 28788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !!wpa_auth->conf.wpa_strict_rekey, 28798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dot11RSNAConfigGroupUpdateCount, 28808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dot11RSNAConfigPairwiseUpdateCount, 28818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_cipher_bits(wpa_auth->conf.wpa_group), 28828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dot11RSNAConfigPMKLifetime, 28838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dot11RSNAConfigPMKReauthThreshold, 28848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dot11RSNAConfigSATimeout, 28858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteSelected), 28868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherSelected), 28878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherSelected), 28888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmkid_txt, 28898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteRequested), 28908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherRequested), 28918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherRequested), 28928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNATKIPCounterMeasuresInvoked, 28938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNA4WayHandshakeFailures); 28948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || (size_t) ret >= buflen - len) 28958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 28968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 28978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot11RSNAConfigPairwiseCiphersTable */ 28998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot11RSNAConfigAuthenticationSuitesTable */ 29008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Private MIB */ 29028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, "hostapdWPAGroupState=%d\n", 29038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->group->wpa_group_state); 29048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || (size_t) ret >= buflen - len) 29058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 29068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 29078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 29098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 29108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen) 29138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 29148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int len = 0, ret; 29158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 pairwise = 0; 29168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 29188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 29198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: FF-FF-FF-FF-FF-FF entry for broadcast/multicast stats */ 29218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* dot11RSNAStatsEntry */ 29238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA) { 29258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pairwise == WPA_CIPHER_CCMP) 29268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pairwise = WPA_CIPHER_SUITE_CCMP; 29278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->pairwise == WPA_CIPHER_TKIP) 29288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pairwise = WPA_CIPHER_SUITE_TKIP; 29298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->pairwise == WPA_CIPHER_WEP104) 29308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pairwise = WPA_CIPHER_SUITE_WEP104; 29318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->pairwise == WPA_CIPHER_WEP40) 29328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pairwise = WPA_CIPHER_SUITE_WEP40; 29338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->pairwise == WPA_CIPHER_NONE) 29348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pairwise = WPA_CIPHER_SUITE_NONE; 29358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (sm->wpa == WPA_VERSION_WPA2) { 29368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pairwise == WPA_CIPHER_CCMP) 29378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pairwise = RSN_CIPHER_SUITE_CCMP; 293861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt else if (sm->pairwise == WPA_CIPHER_GCMP) 293961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pairwise = RSN_CIPHER_SUITE_GCMP; 29408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->pairwise == WPA_CIPHER_TKIP) 29418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pairwise = RSN_CIPHER_SUITE_TKIP; 29428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->pairwise == WPA_CIPHER_WEP104) 29438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pairwise = RSN_CIPHER_SUITE_WEP104; 29448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->pairwise == WPA_CIPHER_WEP40) 29458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pairwise = RSN_CIPHER_SUITE_WEP40; 29468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->pairwise == WPA_CIPHER_NONE) 29478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pairwise = RSN_CIPHER_SUITE_NONE; 29488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 29498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 29508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf( 29528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf + len, buflen - len, 29538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot11RSNAStatsIndex */ 29548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAStatsSTAAddress=" MACSTR "\n" 29558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAStatsVersion=1\n" 29568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAStatsSelectedPairwiseCipher=" RSN_SUITE "\n" 29578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot11RSNAStatsTKIPICVErrors */ 29588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAStatsTKIPLocalMICFailures=%u\n" 29598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAStatsTKIPRemoteMICFailures=%u\n" 29608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot11RSNAStatsCCMPReplays */ 29618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot11RSNAStatsCCMPDecryptErrors */ 29628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot11RSNAStatsTKIPReplays */, 29638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(sm->addr), 29648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SUITE_ARG(pairwise), 29658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAStatsTKIPLocalMICFailures, 29668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAStatsTKIPRemoteMICFailures); 29678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || (size_t) ret >= buflen - len) 29688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 29698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 29708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Private MIB */ 29728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, 29738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "hostapdWPAPTKState=%d\n" 29748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "hostapdWPAPTKGroupState=%d\n", 29758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ptk_state, 29768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ptk_group_state); 29778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || (size_t) ret >= buflen - len) 29788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 29798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 29808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 29828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 29838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth) 29868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 29878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth) 29888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNATKIPCounterMeasuresInvoked++; 29898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 29908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_pairwise_set(struct wpa_state_machine *sm) 29938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 29948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm && sm->pairwise_set; 29958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 29968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_get_pairwise(struct wpa_state_machine *sm) 29998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 30008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->pairwise; 30018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 30028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm) 30058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 30068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 30078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 30088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->wpa_key_mgmt; 30098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 30108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_sta_wpa_version(struct wpa_state_machine *sm) 30138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 30148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 30158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 30168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->wpa; 30178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 30188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm, 30218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *entry) 30228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 30238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL || sm->pmksa != entry) 30248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 30258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmksa = NULL; 30268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 30278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 30288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct rsn_pmksa_cache_entry * 30318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_auth_sta_get_pmksa(struct wpa_state_machine *sm) 30328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 30338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm ? sm->pmksa : NULL; 30348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 30358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm) 30388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 30398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm) 30408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAStatsTKIPLocalMICFailures++; 30418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 30428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, size_t *len) 30458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 30468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL) 30478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 30488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = wpa_auth->wpa_ie_len; 30498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->wpa_ie; 30508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 30518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk, 30548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int session_timeout, struct eapol_state_machine *eapol) 30558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3056c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt if (sm == NULL || sm->wpa != WPA_VERSION_WPA2 || 3057c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt sm->wpa_auth->conf.disable_pmksa_caching) 30588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 30598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, PMK_LEN, 30618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_auth->addr, sm->addr, session_timeout, 30628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol, sm->wpa_key_mgmt)) 30638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 30648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 30668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 30678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth, 30708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pmk, size_t len, const u8 *sta_addr, 30718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int session_timeout, 30728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *eapol) 30738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 30748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL) 30758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 30768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, len, wpa_auth->addr, 30788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta_addr, session_timeout, eapol, 30798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_MGMT_IEEE8021X)) 30808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 30818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 30838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 30848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_group * 30878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id) 30888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 30898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group; 30908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL || wpa_auth->group == NULL) 30928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 30938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Add group state machine for VLAN-ID %d", 30958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vlan_id); 30961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt group = wpa_group_init(wpa_auth, vlan_id, 0); 30978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group == NULL) 30988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 30998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->next = wpa_auth->group->next; 31018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->group->next = group; 31028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return group; 31048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 31058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id) 31088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 31098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group; 31108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL || sm->wpa_auth == NULL) 31128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 31138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = sm->wpa_auth->group; 31158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (group) { 31168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group->vlan_id == vlan_id) 31178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 31188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = group->next; 31198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 31208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group == NULL) { 31228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = wpa_auth_add_group(sm->wpa_auth, vlan_id); 31238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group == NULL) 31248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 31258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 31268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->group == group) 31288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 31298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR " to use group state " 31318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "machine for VLAN ID %d", MAC2STR(sm->addr), vlan_id); 31328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group = group; 31348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 31358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 31368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth, 31398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm, int ack) 31408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 31418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL || sm == NULL) 31428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 31438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key TX status for STA " MACSTR 31448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " ack=%d", MAC2STR(sm->addr), ack); 31458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pending_1_of_4_timeout && ack) { 31468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 31478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Some deployed supplicant implementations update their SNonce 31488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * for each EAPOL-Key 2/4 message even within the same 4-way 31498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * handshake and then fail to use the first SNonce when 31508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * deriving the PTK. This results in unsuccessful 4-way 31518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * handshake whenever the relatively short initial timeout is 31528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * reached and EAPOL-Key 1/4 is retransmitted. Try to work 31538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * around this by increasing the timeout now that we know that 31548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the station has received the frame. 31558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 31568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int timeout_ms = eapol_key_timeout_subseq; 31578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Increase initial EAPOL-Key 1/4 " 31588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "timeout by %u ms because of acknowledged frame", 31598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeout_ms); 31608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm); 31618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(timeout_ms / 1000, 31628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (timeout_ms % 1000) * 1000, 31638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_send_eapol_timeout, wpa_auth, sm); 31648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 31658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3166