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