18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 21f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * IEEE 802.11 RSN / WPA Authenticator 3807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * Copyright (c) 2004-2015, 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" 14cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#include "utils/bitfield.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/aes_wrap.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/crypto.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha1.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha256.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eapol_auth/eapol_auth_sm.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap_config.h" 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ieee802_11.h" 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_auth.h" 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "pmksa_cache_auth.h" 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_auth_i.h" 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_auth_ie.h" 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STATE_MACHINE_DATA struct wpa_state_machine 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STATE_MACHINE_DEBUG_PREFIX "WPA" 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STATE_MACHINE_ADDR sm->addr 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx); 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_sm_step(struct wpa_state_machine *sm); 366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_verify_key_mic(int akmp, struct wpa_ptk *PTK, u8 *data, 376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt size_t data_len); 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx); 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_group_sm_step(struct wpa_authenticator *wpa_auth, 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group); 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_request_new_ptk(struct wpa_state_machine *sm); 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_gtk_update(struct wpa_authenticator *wpa_auth, 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group); 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth, 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group); 466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce, 47d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt const u8 *pmk, unsigned int pmk_len, 48d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct wpa_ptk *ptk); 491d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidtstatic void wpa_group_free(struct wpa_authenticator *wpa_auth, 501d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt struct wpa_group *group); 511d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidtstatic void wpa_group_get(struct wpa_authenticator *wpa_auth, 521d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt struct wpa_group *group); 531d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidtstatic void wpa_group_put(struct wpa_authenticator *wpa_auth, 541d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt struct wpa_group *group); 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u32 dot11RSNAConfigGroupUpdateCount = 4; 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u32 dot11RSNAConfigPairwiseUpdateCount = 4; 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u32 eapol_key_timeout_first = 100; /* ms */ 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u32 eapol_key_timeout_subseq = 1000; /* ms */ 601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic const u32 eapol_key_timeout_first_group = 500; /* ms */ 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* TODO: make these configurable */ 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const int dot11RSNAConfigPMKLifetime = 43200; 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const int dot11RSNAConfigPMKReauthThreshold = 70; 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const int dot11RSNAConfigSATimeout = 60; 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 68d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic inline int wpa_auth_mic_failure_report( 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_authenticator *wpa_auth, const u8 *addr) 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.mic_failure_report) 72d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return wpa_auth->cb.mic_failure_report(wpa_auth->cb.ctx, addr); 73d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return 0; 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 77dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidtstatic inline void wpa_auth_psk_failure_report( 78dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt struct wpa_authenticator *wpa_auth, const u8 *addr) 79dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt{ 80dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt if (wpa_auth->cb.psk_failure_report) 81dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt wpa_auth->cb.psk_failure_report(wpa_auth->cb.ctx, addr); 82dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt} 83dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt 84dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline void wpa_auth_set_eapol(struct wpa_authenticator *wpa_auth, 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, wpa_eapol_variable var, 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int value) 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.set_eapol) 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->cb.set_eapol(wpa_auth->cb.ctx, addr, var, value); 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline int wpa_auth_get_eapol(struct wpa_authenticator *wpa_auth, 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, wpa_eapol_variable var) 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.get_eapol == NULL) 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->cb.get_eapol(wpa_auth->cb.ctx, addr, var); 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth, 104391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt const u8 *addr, 105391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt const u8 *p2p_dev_addr, 106391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt const u8 *prev_psk) 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.get_psk == NULL) 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 110391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return wpa_auth->cb.get_psk(wpa_auth->cb.ctx, addr, p2p_dev_addr, 111391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt prev_psk); 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline int wpa_auth_get_msk(struct wpa_authenticator *wpa_auth, 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, u8 *msk, size_t *len) 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.get_msk == NULL) 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->cb.get_msk(wpa_auth->cb.ctx, addr, msk, len); 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int vlan_id, 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wpa_alg alg, const u8 *addr, int idx, 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key, size_t key_len) 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.set_key == NULL) 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->cb.set_key(wpa_auth->cb.ctx, vlan_id, alg, addr, idx, 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key, key_len); 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth, 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, int idx, u8 *seq) 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.get_seqnum == NULL) 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->cb.get_seqnum(wpa_auth->cb.ctx, addr, idx, seq); 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline int 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr, 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *data, size_t data_len, int encrypt) 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.send_eapol == NULL) 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->cb.send_eapol(wpa_auth->cb.ctx, addr, data, data_len, 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encrypt); 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_MESH 1576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic inline int wpa_auth_start_ampe(struct wpa_authenticator *wpa_auth, 1586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *addr) 1596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 1606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (wpa_auth->cb.start_ampe == NULL) 1616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 1626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return wpa_auth->cb.start_ampe(wpa_auth->cb.ctx, addr); 1636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 1646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_MESH */ 1656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth, 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int (*cb)(struct wpa_state_machine *sm, void *ctx), 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *cb_ctx) 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.for_each_sta == NULL) 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->cb.for_each_sta(wpa_auth->cb.ctx, cb, cb_ctx); 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth, 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int (*cb)(struct wpa_authenticator *a, void *ctx), 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *cb_ctx) 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.for_each_auth == NULL) 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->cb.for_each_auth(wpa_auth->cb.ctx, cb, cb_ctx); 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr, 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt logger_level level, const char *txt) 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.logger == NULL) 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->cb.logger(wpa_auth->cb.ctx, addr, level, txt); 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr, 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt logger_level level, const char *fmt, ...) 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *format; 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int maxlen; 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt va_list ap; 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.logger == NULL) 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt maxlen = os_strlen(fmt) + 100; 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt format = os_malloc(maxlen); 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!format) 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt va_start(ap, fmt); 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vsnprintf(format, maxlen, fmt, ap); 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt va_end(ap); 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, addr, level, format); 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(format); 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth, 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr) 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->cb.disconnect == NULL) 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR, MAC2STR(addr)); 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->cb.disconnect(wpa_auth->cb.ctx, addr, 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_REASON_PREV_AUTH_NOT_VALID); 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_use_aes_cmac(struct wpa_state_machine *sm) 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 1; 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_sha256(sm->wpa_key_mgmt)) 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 1; 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 243f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) 244f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ret = 1; 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx) 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_authenticator *wpa_auth = eloop_ctx; 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(wpa_auth->group->GMK, WPA_GMK_LEN)) { 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Failed to get random data for WPA " 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "initialization."); 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "GMK rekeyd"); 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "GMK", 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->group->GMK, WPA_GMK_LEN); 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->conf.wpa_gmk_rekey) { 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0, 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_rekey_gmk, wpa_auth, NULL); 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx) 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_authenticator *wpa_auth = eloop_ctx; 2721d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt struct wpa_group *group, *next; 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "rekeying GTK"); 2751d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt group = wpa_auth->group; 2761d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt while (group) { 2771d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt wpa_group_get(wpa_auth, group); 2781d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTKReKey = TRUE; 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt do { 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->changed = FALSE; 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_sm_step(wpa_auth, group); 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } while (group->changed); 2841d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt 2851d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt next = group->next; 2861d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt wpa_group_put(wpa_auth, group); 2871d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt group = next; 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->conf.wpa_group_rekey) { 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, wpa_rekey_gtk, wpa_auth, NULL); 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_rekey_ptk(void *eloop_ctx, void *timeout_ctx) 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_authenticator *wpa_auth = eloop_ctx; 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm = timeout_ctx; 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "rekeying PTK"); 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_request_new_ptk(sm); 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_step(sm); 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_auth_pmksa_clear_cb(struct wpa_state_machine *sm, void *ctx) 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pmksa == ctx) 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmksa = NULL; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_auth_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry, 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *ctx) 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_authenticator *wpa_auth = ctx; 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_for_each_sta(wpa_auth, wpa_auth_pmksa_clear_cb, entry); 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_group_init_gmk_and_counter(struct wpa_authenticator *wpa_auth, 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group) 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 327a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt u8 buf[ETH_ALEN + 8 + sizeof(unsigned long)]; 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rkey[32]; 329a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt unsigned long ptr; 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(group->GMK, WPA_GMK_LEN) < 0) 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "GMK", group->GMK, WPA_GMK_LEN); 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Counter = PRF-256(Random number, "Init Counter", 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Local MAC Address || Time) 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf, wpa_auth->addr, ETH_ALEN); 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_get_ntp_timestamp(buf + ETH_ALEN); 341a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt ptr = (unsigned long) group; 342a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt os_memcpy(buf + ETH_ALEN + 8, &ptr, sizeof(ptr)); 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(rkey, sizeof(rkey)) < 0) 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sha1_prf(rkey, sizeof(rkey), "Init Counter", buf, sizeof(buf), 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->Counter, WPA_NONCE_LEN) < 0) 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "Key Counter", 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->Counter, WPA_NONCE_LEN); 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth, 3571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int vlan_id, int delay_init) 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group; 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = os_zalloc(sizeof(struct wpa_group)); 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group == NULL) 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTKAuthenticator = TRUE; 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->vlan_id = vlan_id; 3674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group); 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_pool_ready() != 1) { 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPA: Not enough entropy in random pool " 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for secure operations - update keys later when " 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the first station connects"); 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Set initial GMK/Counter value here. The actual values that will be 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * used in negotiations will be set once the first station tries to 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * connect. This allows more time for collecting additional randomness 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * on embedded devices. 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0) { 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Failed to get random data for WPA " 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "initialization."); 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(group); 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GInit = TRUE; 3891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (delay_init) { 3901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Delay group state machine start " 3911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "until Beacon frames have been configured"); 3921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Initialization is completed in wpa_init_keys(). */ 3931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else { 3941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_group_sm_step(wpa_auth, group); 3951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt group->GInit = FALSE; 3961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_group_sm_step(wpa_auth, group); 3971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return group; 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_init - Initialize WPA authenticator 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: Authenticator address 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @conf: Configuration for WPA authenticator 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cb: Callback functions for WPA authenticator 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to WPA authenticator data or %NULL on failure 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_authenticator * wpa_init(const u8 *addr, 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_auth_config *conf, 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_auth_callbacks *cb) 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_authenticator *wpa_auth; 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth = os_zalloc(sizeof(struct wpa_authenticator)); 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL) 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wpa_auth->addr, addr, ETH_ALEN); 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&wpa_auth->conf, conf, sizeof(*conf)); 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&wpa_auth->cb, cb, sizeof(*cb)); 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_gen_wpa_ie(wpa_auth)) { 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not generate WPA IE."); 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth); 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_auth->group = wpa_group_init(wpa_auth, 0, 1); 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->group == NULL) { 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth->wpa_ie); 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth); 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->pmksa = pmksa_cache_auth_init(wpa_auth_pmksa_free_cb, 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth); 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->pmksa == NULL) { 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "PMKSA cache initialization failed."); 440ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt os_free(wpa_auth->group); 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth->wpa_ie); 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth); 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->ft_pmk_cache = wpa_ft_pmk_cache_init(); 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->ft_pmk_cache == NULL) { 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "FT PMK cache initialization failed."); 450ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt os_free(wpa_auth->group); 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth->wpa_ie); 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_cache_auth_deinit(wpa_auth->pmksa); 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth); 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->conf.wpa_gmk_rekey) { 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0, 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_rekey_gmk, wpa_auth, NULL); 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->conf.wpa_group_rekey) { 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, 0, 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_rekey_gtk, wpa_auth, NULL); 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 468cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_P2P 469cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (WPA_GET_BE32(conf->ip_addr_start)) { 470cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt int count = WPA_GET_BE32(conf->ip_addr_end) - 471cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt WPA_GET_BE32(conf->ip_addr_start) + 1; 472cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (count > 1000) 473cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt count = 1000; 474cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (count > 0) 475cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_auth->ip_pool = bitfield_alloc(count); 476cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 477cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_P2P */ 478cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth; 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint wpa_init_keys(struct wpa_authenticator *wpa_auth) 4841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 4851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_group *group = wpa_auth->group; 4861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Start group state machine to set initial " 4881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "keys"); 4891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_group_sm_step(wpa_auth, group); 4901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt group->GInit = FALSE; 4911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_group_sm_step(wpa_auth, group); 492fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) 493fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return -1; 4941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 4951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 4961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_deinit - Deinitialize WPA authenticator 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_auth: Pointer to WPA authenticator data from wpa_init() 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_deinit(struct wpa_authenticator *wpa_auth) 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group, *prev; 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_rekey_gmk, wpa_auth, NULL); 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL); 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (wpa_auth->stsl_negotiations) 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_stsl_remove(wpa_auth, wpa_auth->stsl_negotiations); 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_cache_auth_deinit(wpa_auth->pmksa); 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ft_pmk_cache_deinit(wpa_auth->ft_pmk_cache); 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->ft_pmk_cache = NULL; 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 521cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_P2P 522cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt bitfield_free(wpa_auth->ip_pool); 523cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_P2P */ 524cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 525cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth->wpa_ie); 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = wpa_auth->group; 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (group) { 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = group; 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = group->next; 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(prev); 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth); 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_reconfig - Update WPA authenticator configuration 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_auth: Pointer to WPA authenticator data from wpa_init() 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @conf: Configuration for WPA authenticator 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_reconfig(struct wpa_authenticator *wpa_auth, 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_auth_config *conf) 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group; 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL) 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&wpa_auth->conf, conf, sizeof(*conf)); 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_gen_wpa_ie(wpa_auth)) { 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not generate WPA IE."); 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Reinitialize GTK to make sure it is suitable for the new 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * configuration. 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = wpa_auth->group; 5624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group); 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GInit = TRUE; 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_sm_step(wpa_auth, group); 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GInit = FALSE; 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_sm_step(wpa_auth, group); 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_state_machine * 573391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtwpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr, 574391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt const u8 *p2p_dev_addr) 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm; 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 578fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (wpa_auth->group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) 579fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return NULL; 580fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm = os_zalloc(sizeof(struct wpa_state_machine)); 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->addr, addr, ETH_ALEN); 585391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (p2p_dev_addr) 586391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt os_memcpy(sm->p2p_dev_addr, p2p_dev_addr, ETH_ALEN); 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_auth = wpa_auth; 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group = wpa_auth->group; 5901d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt wpa_group_get(sm->wpa_auth, sm->group); 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm; 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm) 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->ft_completed) { 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FT authentication already completed - do not " 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "start 4-way handshake"); 607717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt /* Go to PTKINITDONE state to allow GTK rekeying */ 608717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt sm->wpa_ptk_state = WPA_PTK_PTKINITDONE; 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->started) { 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&sm->key_replay, 0, sizeof(sm->key_replay)); 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ReAuthenticationRequest = TRUE; 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_sm_step(sm); 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "start authentication"); 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->started = 1; 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->Init = TRUE; 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_step(sm) == 1) 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; /* should not really happen */ 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->Init = FALSE; 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->AuthenticationRequest = TRUE; 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_sm_step(sm); 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_auth_sta_no_wpa(struct wpa_state_machine *sm) 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* WPA/RSN was not used - clear WPA state. This is needed if the STA 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * reassociates back to the same AP while the previous entry for the 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * STA has not yet been removed. */ 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_key_mgmt = 0; 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_free_sta_sm(struct wpa_state_machine *sm) 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 646cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_P2P 647cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (WPA_GET_BE32(sm->ip_addr)) { 648cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt u32 start; 649cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_DEBUG, "P2P: Free assigned IP " 650cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt "address %u.%u.%u.%u from " MACSTR, 651cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt sm->ip_addr[0], sm->ip_addr[1], 652cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt sm->ip_addr[2], sm->ip_addr[3], 653cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt MAC2STR(sm->addr)); 654cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt start = WPA_GET_BE32(sm->wpa_auth->conf.ip_addr_start); 655cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt bitfield_clear(sm->wpa_auth->ip_pool, 656cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt WPA_GET_BE32(sm->ip_addr) - start); 657cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 658cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_P2P */ 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->GUpdateStationKeys) { 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group->GKeyDoneStations--; 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GUpdateStationKeys = FALSE; 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->assoc_resp_ftie); 665d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt wpabuf_free(sm->ft_pending_req_ies); 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->last_rx_eapol_key); 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->wpa_ie); 6691d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt wpa_group_put(sm->wpa_auth, sm->group); 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm); 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_auth_sta_deinit(struct wpa_state_machine *sm) 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) { 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "strict rekeying - force GTK rekey since STA " 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "is leaving"); 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_rekey_gtk, sm->wpa_auth, NULL); 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(0, 500000, wpa_rekey_gtk, sm->wpa_auth, 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL); 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm); 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pending_1_of_4_timeout = 0; 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_sm_call_step, sm, NULL); 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->in_step_loop) { 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Must not free state machine while wpa_sm_step() is running. 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Freeing will be completed in the end of wpa_sm_step(). */ 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Registering pending STA state " 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "machine deinit for " MACSTR, MAC2STR(sm->addr)); 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pending_deinit = 1; 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_free_sta_sm(sm); 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_request_new_ptk(struct wpa_state_machine *sm) 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PTKRequest = TRUE; 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PTK_valid = 0; 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 713c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic int wpa_replay_counter_valid(struct wpa_key_replay_counter *ctr, 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *replay_counter) 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { 718c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (!ctr[i].valid) 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 720c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (os_memcmp(replay_counter, ctr[i].counter, 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN) == 0) 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 728c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic void wpa_replay_counter_mark_invalid(struct wpa_key_replay_counter *ctr, 729c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt const u8 *replay_counter) 730c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{ 731c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt int i; 732c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { 733c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (ctr[i].valid && 734c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt (replay_counter == NULL || 735c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt os_memcmp(replay_counter, ctr[i].counter, 736c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt WPA_REPLAY_COUNTER_LEN) == 0)) 737c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt ctr[i].valid = FALSE; 738c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 739c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt} 740c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 741c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth, 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm, 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *kde) 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data ie; 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_mdie *mdie; 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0 || 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie.num_pmkid != 1 || ie.pmkid == NULL) { 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "FT: No PMKR1Name in " 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FT 4-way handshake message 2/4"); 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->sup_pmk_r1_name, ie.pmkid, PMKID_LEN); 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Supplicant", 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->sup_pmk_r1_name, PMKID_LEN); 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!kde->mdie || !kde->ftie) { 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "FT: No %s in FT 4-way handshake " 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message 2/4", kde->mdie ? "FTIE" : "MDIE"); 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mdie = (struct rsn_mdie *) (kde->mdie + 2); 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde->mdie[1] < sizeof(struct rsn_mdie) || 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(wpa_auth->conf.mobility_domain, mdie->mobility_domain, 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MOBILITY_DOMAIN_ID_LEN) != 0) { 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "FT: MDIE mismatch"); 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->assoc_resp_ftie && 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (kde->ftie[1] != sm->assoc_resp_ftie[1] || 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(kde->ftie, sm->assoc_resp_ftie, 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + sm->assoc_resp_ftie[1]) != 0)) { 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "FT: FTIE mismatch"); 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 2/4", 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde->ftie, kde->ftie_len); 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)AssocResp", 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->assoc_resp_ftie, 2 + sm->assoc_resp_ftie[1]); 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 792d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic int wpa_receive_error_report(struct wpa_authenticator *wpa_auth, 793d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt struct wpa_state_machine *sm, int group) 7941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 7951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Supplicant reported a Michael MIC error */ 7961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, 7971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "received EAPOL-Key Error Request " 7981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "(STA detected Michael MIC failure (group=%d))", 7991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt group); 8001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (group && wpa_auth->conf.wpa_group != WPA_CIPHER_TKIP) { 8021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 8031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "ignore Michael MIC failure report since " 8041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "group cipher is not TKIP"); 8051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else if (!group && sm->pairwise != WPA_CIPHER_TKIP) { 8061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 8071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "ignore Michael MIC failure report since " 8081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "pairwise cipher is not TKIP"); 8091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else { 810d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (wpa_auth_mic_failure_report(wpa_auth, sm->addr) > 0) 811d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return 1; /* STA entry was removed */ 8121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt sm->dot11RSNAStatsTKIPRemoteMICFailures++; 8131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_auth->dot11RSNAStatsTKIPRemoteMICFailures++; 8141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 8151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 8171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Error report is not a request for a new key handshake, but since 8181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Authenticator may do it, let's change the keys now anyway. 8191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 8201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_request_new_ptk(sm); 821d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return 0; 8221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 8231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data, 8266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt size_t data_len) 8276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 8286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_ptk PTK; 8296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ok = 0; 8306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *pmk = NULL; 831d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt unsigned int pmk_len; 8326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 8336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt for (;;) { 8346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { 8356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, 8366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sm->p2p_dev_addr, pmk); 8376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (pmk == NULL) 8386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 839d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt pmk_len = PMK_LEN; 840d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } else { 8416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt pmk = sm->PMK; 842d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt pmk_len = sm->pmk_len; 843d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 8446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 845d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK); 8466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 8476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (wpa_verify_key_mic(sm->wpa_key_mgmt, &PTK, data, data_len) 8486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt == 0) { 8496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ok = 1; 8506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 8516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 8526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 8536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) 8546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 8556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 8566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 8576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!ok) { 8586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 8596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "WPA: Earlier SNonce did not result in matching MIC"); 8606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 8616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 8626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 8636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 8646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "WPA: Earlier SNonce resulted in matching MIC"); 8656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sm->alt_snonce_valid = 0; 8666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(sm->SNonce, sm->alt_SNonce, WPA_NONCE_LEN); 8676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(&sm->PTK, &PTK, sizeof(PTK)); 8686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sm->PTK_valid = TRUE; 8696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 8706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 8716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 8726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 8736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_receive(struct wpa_authenticator *wpa_auth, 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm, 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *data, size_t data_len) 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee802_1x_hdr *hdr; 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *key; 880807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt struct wpa_eapol_key_192 *key192; 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info, key_data_length; 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST, 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SMK_M1, SMK_M3, SMK_ERROR } msg; 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *msgtxt; 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ft; 887807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt const u8 *eapol_key_ie, *key_data; 888807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt size_t eapol_key_ie_len, keyhdrlen, mic_len; 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 893807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt mic_len = wpa_mic_len(sm->wpa_key_mgmt); 894807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt keyhdrlen = mic_len == 24 ? sizeof(*key192) : sizeof(*key); 895807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 896807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (data_len < sizeof(*hdr) + keyhdrlen) 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct ieee802_1x_hdr *) data; 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = (struct wpa_eapol_key *) (hdr + 1); 901807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt key192 = (struct wpa_eapol_key_192 *) (hdr + 1); 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = WPA_GET_BE16(key->key_info); 903807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (mic_len == 24) { 904807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt key_data = (const u8 *) (key192 + 1); 905807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt key_data_length = WPA_GET_BE16(key192->key_data_length); 906807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt } else { 907807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt key_data = (const u8 *) (key + 1); 908807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt key_data_length = WPA_GET_BE16(key->key_data_length); 909807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt } 9101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR 9111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " key_info=0x%x type=%u key_data_length=%u", 9121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(sm->addr), key_info, key->type, key_data_length); 913807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (key_data_length > data_len - sizeof(*hdr) - keyhdrlen) { 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPA: Invalid EAPOL-Key frame - " 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "key_data overflow (%d > %lu)", 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_data_length, 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) (data_len - sizeof(*hdr) - 918807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt keyhdrlen)); 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA2) { 923c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (key->type == EAPOL_KEY_TYPE_WPA) { 924c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 925c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * Some deployed station implementations seem to send 926c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * msg 4/4 with incorrect type value in WPA2 mode. 927c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 928c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_DEBUG, "Workaround: Allow EAPOL-Key " 929c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "with unexpected WPA type in RSN mode"); 930c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } else if (key->type != EAPOL_KEY_TYPE_RSN) { 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with " 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unexpected type %d in RSN mode", 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->type); 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key->type != EAPOL_KEY_TYPE_WPA) { 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with " 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unexpected type %d in WPA mode", 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->type); 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Received Key Nonce", key->key_nonce, 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_NONCE_LEN); 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Received Replay Counter", 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->replay_counter, WPA_REPLAY_COUNTER_LEN); 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: verify that the EAPOL-Key frame was encrypted if pairwise keys 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * are set */ 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((key_info & (WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_REQUEST)) == 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_REQUEST)) { 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_ERROR) { 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = SMK_ERROR; 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msgtxt = "SMK Error"; 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = SMK_M1; 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msgtxt = "SMK M1"; 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) { 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = SMK_M3; 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msgtxt = "SMK M3"; 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_info & WPA_KEY_INFO_REQUEST) { 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = REQUEST; 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msgtxt = "Request"; 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (!(key_info & WPA_KEY_INFO_KEY_TYPE)) { 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = GROUP_2; 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msgtxt = "2/2 Group"; 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_data_length == 0) { 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = PAIRWISE_4; 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msgtxt = "4/4 Pairwise"; 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = PAIRWISE_2; 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msgtxt = "2/4 Pairwise"; 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: key_info type validation for PeerKey */ 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == REQUEST || msg == PAIRWISE_2 || msg == PAIRWISE_4 || 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg == GROUP_2) { 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 ver = key_info & WPA_KEY_INFO_TYPE_MASK; 98361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->pairwise == WPA_CIPHER_CCMP || 98461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sm->pairwise == WPA_CIPHER_GCMP) { 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_use_aes_cmac(sm) && 986f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN && 9876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt !wpa_key_mgmt_suite_b(sm->wpa_key_mgmt) && 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt LOGGER_WARNING, 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "advertised support for " 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "AES-128-CMAC, but did not " 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "use it"); 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_use_aes_cmac(sm) && 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt LOGGER_WARNING, 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "did not use HMAC-SHA1-AES " 100261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "with CCMP/GCMP"); 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 10076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (wpa_key_mgmt_suite_b(sm->wpa_key_mgmt) && 10086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) { 10096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING, 10106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "did not use EAPOL-Key descriptor version 0 as required for AKM-defined cases"); 10116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return; 10126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_REQUEST) { 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->req_replay_counter_used && 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(key->replay_counter, sm->req_replay_counter, 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN) <= 0) { 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING, 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key request with " 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "replayed counter"); 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(key_info & WPA_KEY_INFO_REQUEST) && 1027c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt !wpa_replay_counter_valid(sm->key_replay, key->replay_counter)) { 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 1029c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 1030c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (msg == PAIRWISE_2 && 1031c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_replay_counter_valid(sm->prev_key_replay, 1032c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt key->replay_counter) && 1033c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING && 1034c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt os_memcmp(sm->SNonce, key->key_nonce, WPA_NONCE_LEN) != 0) 1035c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt { 1036c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 1037c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * Some supplicant implementations (e.g., Windows XP 1038c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * WZC) update SNonce for each EAPOL-Key 2/4. This 1039c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * breaks the workaround on accepting any of the 1040c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * pending requests, so allow the SNonce to be updated 1041c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * even if we have already sent out EAPOL-Key 3/4. 1042c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 1043c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, 1044c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "Process SNonce update from STA " 1045c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "based on retransmitted EAPOL-Key " 1046c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "1/4"); 1047c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sm->update_snonce = 1; 10486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(sm->alt_SNonce, sm->SNonce, WPA_NONCE_LEN); 10496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sm->alt_snonce_valid = TRUE; 10506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(sm->alt_replay_counter, 10516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sm->key_replay[0].counter, 10526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WPA_REPLAY_COUNTER_LEN); 10536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto continue_processing; 10546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 10556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 10566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (msg == PAIRWISE_4 && sm->alt_snonce_valid && 10576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING && 10586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcmp(key->replay_counter, sm->alt_replay_counter, 10596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WPA_REPLAY_COUNTER_LEN) == 0) { 10606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* 10616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Supplicant may still be using the old SNonce since 10626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * there was two EAPOL-Key 2/4 messages and they had 10636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * different SNonce values. 10646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 10656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, 10666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "Try to process received EAPOL-Key 4/4 based on old Replay Counter and SNonce from an earlier EAPOL-Key 1/4"); 1067c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt goto continue_processing; 1068c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 1069c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 1070c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (msg == PAIRWISE_2 && 1071c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_replay_counter_valid(sm->prev_key_replay, 1072c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt key->replay_counter) && 1073c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING) { 1074c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, 1075c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "ignore retransmitted EAPOL-Key %s - " 1076c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "SNonce did not change", msgtxt); 1077c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } else { 1078c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, 1079c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "received EAPOL-Key %s with " 1080c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "unexpected replay counter", msgtxt); 1081c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->key_replay[i].valid) 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "pending replay counter", 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->key_replay[i].counter, 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "received replay counter", 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->replay_counter, WPA_REPLAY_COUNTER_LEN); 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1094c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtcontinue_processing: 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (msg) { 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PAIRWISE_2: 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_ptk_state != WPA_PTK_PTKSTART && 1098c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sm->wpa_ptk_state != WPA_PTK_PTKCALCNEGOTIATING && 1099c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt (!sm->update_snonce || 1100c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING)) { 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key msg 2/4 in " 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "invalid state (%d) - dropped", 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ptk_state); 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt random_add_randomness(key->key_nonce, WPA_NONCE_LEN); 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->group->reject_4way_hs_for_entropy) { 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The system did not have enough entropy to generate 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * strong random numbers. Reject the first 4-way 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * handshake(s) and collect some entropy based on the 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * information from it. Once enough entropy is 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * available, the next atempt will trigger GMK/Key 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Counter update and the station will be allowed to 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * continue. 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Reject 4-way handshake to " 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "collect more entropy for random number " 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "generation"); 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt random_mark_pool_ready(); 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sta_disconnect(wpa_auth, sm->addr); 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1125807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) { 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key msg 2/4 with " 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "invalid Key Data contents"); 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie) { 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_key_ie = kde.rsn_ie; 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_key_ie_len = kde.rsn_ie_len; 1134f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } else if (kde.osen) { 1135f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt eapol_key_ie = kde.osen; 1136f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt eapol_key_ie_len = kde.osen_len; 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_key_ie = kde.wpa_ie; 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_key_ie_len = kde.wpa_ie_len; 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ft = sm->wpa == WPA_VERSION_WPA2 && 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_key_mgmt_ft(sm->wpa_key_mgmt); 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_ie == NULL || 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_compare_rsn_ie(ft, 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ie, sm->wpa_ie_len, 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_key_ie, eapol_key_ie_len)) { 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA IE from (Re)AssocReq did not " 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "match with msg 2/4"); 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_ie) { 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA IE in AssocReq", 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ie, sm->wpa_ie_len); 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA IE in msg 2/4", 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_key_ie, eapol_key_ie_len); 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* MLME-DEAUTHENTICATE.request */ 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sta_disconnect(wpa_auth, sm->addr); 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) { 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sta_disconnect(wpa_auth, sm->addr); 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 1166cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_P2P 1167cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (kde.ip_addr_req && kde.ip_addr_req[0] && 1168cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_auth->ip_pool && WPA_GET_BE32(sm->ip_addr) == 0) { 1169cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt int idx; 1170cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_DEBUG, "P2P: IP address requested in " 1171cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt "EAPOL-Key exchange"); 1172cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt idx = bitfield_get_first_zero(wpa_auth->ip_pool); 1173cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (idx >= 0) { 1174cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt u32 start = WPA_GET_BE32(wpa_auth->conf. 1175cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt ip_addr_start); 1176cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt bitfield_set(wpa_auth->ip_pool, idx); 1177cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt WPA_PUT_BE32(sm->ip_addr, start + idx); 1178cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_DEBUG, "P2P: Assigned IP " 1179cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt "address %u.%u.%u.%u to " MACSTR, 1180cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt sm->ip_addr[0], sm->ip_addr[1], 1181cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt sm->ip_addr[2], sm->ip_addr[3], 1182cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt MAC2STR(sm->addr)); 1183cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 1184cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 1185cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_P2P */ 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PAIRWISE_4: 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING || 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !sm->PTK_valid) { 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key msg 4/4 in " 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "invalid state (%d) - dropped", 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ptk_state); 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case GROUP_2: 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_ptk_group_state != WPA_PTK_GROUP_REKEYNEGOTIATING 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt || !sm->PTK_valid) { 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, 12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key msg 2/2 in " 12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "invalid state (%d) - dropped", 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ptk_group_state); 12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SMK_M1: 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SMK_M3: 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SMK_ERROR: 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_auth->conf.peerkey) { 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: SMK M1/M3/Error, but " 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PeerKey use disabled - ignoring message"); 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->PTK_valid) { 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key msg SMK in " 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "invalid state - dropped"); 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_PEERKEY */ 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SMK_M1: 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SMK_M3: 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SMK_ERROR: 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; /* STSL disabled - ignore SMK messages */ 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case REQUEST: 12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key frame (%s)", msgtxt); 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_ACK) { 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received invalid EAPOL-Key: Key Ack set"); 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(key_info & WPA_KEY_INFO_MIC)) { 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received invalid EAPOL-Key: Key MIC not set"); 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->MICVerified = FALSE; 1249c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (sm->PTK_valid && !sm->update_snonce) { 12506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (wpa_verify_key_mic(sm->wpa_key_mgmt, &sm->PTK, data, 12516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt data_len) && 12526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (msg != PAIRWISE_4 || !sm->alt_snonce_valid || 12536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_try_alt_snonce(sm, data, data_len))) { 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key with invalid MIC"); 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->MICVerified = TRUE; 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm); 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pending_1_of_4_timeout = 0; 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_REQUEST) { 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->MICVerified) { 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->req_replay_counter_used = 1; 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->req_replay_counter, key->replay_counter, 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key request with " 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "invalid MIC"); 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO: should decrypt key data field if encryption was used; 12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * even though MAC address KDE is not normally encrypted, 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * supplicant is allowed to encrypt it. 12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == SMK_ERROR) { 12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 1282807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_smk_error(wpa_auth, sm, key_data, key_data_length); 12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_info & WPA_KEY_INFO_ERROR) { 1286d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (wpa_receive_error_report( 1287d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_auth, sm, 1288d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt !(key_info & WPA_KEY_INFO_KEY_TYPE)) > 0) 1289d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return; /* STA entry was removed */ 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_info & WPA_KEY_INFO_KEY_TYPE) { 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key Request for new " 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "4-Way Handshake"); 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_request_new_ptk(sm); 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (msg == SMK_M1) { 1297807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_smk_m1(wpa_auth, sm, key, key_data, 12986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt key_data_length); 12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (key_data_length > 0 && 1301807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_parse_kde_ies(key_data, key_data_length, 1302807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt &kde) == 0 && 13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.mac_addr) { 13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received EAPOL-Key Request for GTK " 13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "rekeying"); 13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL); 13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_rekey_gtk(wpa_auth, NULL); 13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1312c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* Do not allow the same key replay counter to be reused. */ 1313c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_replay_counter_mark_invalid(sm->key_replay, 1314c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt key->replay_counter); 1315c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 1316c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (msg == PAIRWISE_2) { 1317c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 1318c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * Maintain a copy of the pending EAPOL-Key frames in 1319c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * case the EAPOL-Key frame was retransmitted. This is 1320c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * needed to allow EAPOL-Key msg 2/4 reply to another 1321c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * pending msg 1/4 to update the SNonce to work around 1322c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * unexpected supplicant behavior. 1323c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 1324c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt os_memcpy(sm->prev_key_replay, sm->key_replay, 1325c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sizeof(sm->key_replay)); 1326c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } else { 1327c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt os_memset(sm->prev_key_replay, 0, 1328c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sizeof(sm->prev_key_replay)); 1329c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 1330c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 1331c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 1332c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * Make sure old valid counters are not accepted anymore and 1333c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * do not get copied again. 1334c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 1335c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_replay_counter_mark_invalid(sm->key_replay, NULL); 13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == SMK_M3) { 1340807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_smk_m3(wpa_auth, sm, key, key_data, key_data_length); 13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->last_rx_eapol_key); 13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->last_rx_eapol_key = os_malloc(data_len); 13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->last_rx_eapol_key == NULL) 13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->last_rx_eapol_key, data, data_len); 13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->last_rx_eapol_key_len = data_len; 13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt sm->rx_eapol_key_secure = !!(key_info & WPA_KEY_INFO_SECURE); 13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->EAPOLKeyReceived = TRUE; 13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE); 13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST); 13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN); 13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_step(sm); 13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr, 13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *gnonce, u8 *gtk, size_t gtk_len) 13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 data[ETH_ALEN + WPA_NONCE_LEN + 8 + 16]; 13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* GTK = PRF-X(GMK, "Group key expansion", 13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AA || GNonce || Time || random data) 13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The example described in the IEEE 802.11 standard uses only AA and 13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * GNonce as inputs here. Add some more entropy since this derivation 13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * is done only at the Authenticator and as such, does not need to be 13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * exactly same. 13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data, addr, ETH_ALEN); 13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN); 13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = data + ETH_ALEN + WPA_NONCE_LEN; 13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_get_ntp_timestamp(pos); 13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 8; 13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(pos, 16) < 0) 13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), gtk, gtk_len); 13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_IEEE80211W */ 13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sha1_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), gtk, gtk_len) 13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt < 0) 13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx) 13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_authenticator *wpa_auth = eloop_ctx; 13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm = timeout_ctx; 13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pending_1_of_4_timeout = 0; 14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "EAPOL-Key timeout"); 14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutEvt = TRUE; 14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_step(sm); 14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid __wpa_send_eapol(struct wpa_authenticator *wpa_auth, 14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm, int key_info, 14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *key_rsc, const u8 *nonce, 14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *kde, size_t kde_len, 14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int keyidx, int encr, int force_version) 14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee802_1x_hdr *hdr; 14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *key; 1415807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt struct wpa_eapol_key_192 *key192; 1416807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt size_t len, mic_len, keyhdrlen; 14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int alg; 14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int key_data_len, pad_len = 0; 14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *pos; 14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int version, pairwise; 14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 1422807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt u8 *key_data; 14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1424807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt mic_len = wpa_mic_len(sm->wpa_key_mgmt); 1425807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt keyhdrlen = mic_len == 24 ? sizeof(*key192) : sizeof(*key); 1426807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 1427807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt len = sizeof(struct ieee802_1x_hdr) + keyhdrlen; 14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (force_version) 14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt version = force_version; 14316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN || 14326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_key_mgmt_suite_b(sm->wpa_key_mgmt)) 1433f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt version = WPA_KEY_INFO_TYPE_AKM_DEFINED; 14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (wpa_use_aes_cmac(sm)) 14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt version = WPA_KEY_INFO_TYPE_AES_128_CMAC; 143661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt else if (sm->pairwise != WPA_CIPHER_TKIP) 14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt version = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; 14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; 14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 144151b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt pairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE); 14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Send EAPOL(version=%d secure=%d mic=%d " 14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ack=%d install=%d pairwise=%d kde_len=%lu keyidx=%d " 14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "encr=%d)", 14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt version, 14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (key_info & WPA_KEY_INFO_SECURE) ? 1 : 0, 14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (key_info & WPA_KEY_INFO_MIC) ? 1 : 0, 14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (key_info & WPA_KEY_INFO_ACK) ? 1 : 0, 14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (key_info & WPA_KEY_INFO_INSTALL) ? 1 : 0, 14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pairwise, (unsigned long) kde_len, keyidx, encr); 14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_data_len = kde_len; 14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || 1456f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN || 14576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_key_mgmt_suite_b(sm->wpa_key_mgmt) || 14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) { 14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad_len = key_data_len % 8; 14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pad_len) 14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad_len = 8 - pad_len; 14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_data_len += pad_len + 8; 14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += key_data_len; 14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = os_zalloc(len); 14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr == NULL) 14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->version = wpa_auth->conf.eapol_version; 14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->type = IEEE802_1X_TYPE_EAPOL_KEY; 14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->length = host_to_be16(len - sizeof(*hdr)); 14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = (struct wpa_eapol_key *) (hdr + 1); 1474807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt key192 = (struct wpa_eapol_key_192 *) (hdr + 1); 1475807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt key_data = ((u8 *) (hdr + 1)) + keyhdrlen; 14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->type = sm->wpa == WPA_VERSION_WPA2 ? 14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; 14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info |= version; 14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (encr && sm->wpa == WPA_VERSION_WPA2) 14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info |= WPA_KEY_INFO_ENCR_KEY_DATA; 14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa != WPA_VERSION_WPA2) 14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info |= keyidx << WPA_KEY_INFO_KEY_INDEX_SHIFT; 14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(key->key_info, key_info); 14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt alg = pairwise ? sm->pairwise : wpa_auth->conf.wpa_group; 14874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt WPA_PUT_BE16(key->key_length, wpa_cipher_key_len(alg)); 14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_SMK_MESSAGE) 14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(key->key_length, 0); 14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: STSL: what to use as key_replay_counter? */ 14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = RSNA_MAX_EAPOL_RETRIES - 1; i > 0; i--) { 14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->key_replay[i].valid = sm->key_replay[i - 1].valid; 14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->key_replay[i].counter, 14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->key_replay[i - 1].counter, 14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(sm->key_replay[0].counter, WPA_REPLAY_COUNTER_LEN); 14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key->replay_counter, sm->key_replay[0].counter, 15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_REPLAY_COUNTER_LEN); 15016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter", 15026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt key->replay_counter, WPA_REPLAY_COUNTER_LEN); 15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->key_replay[0].valid = TRUE; 15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nonce) 15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key->key_nonce, nonce, WPA_NONCE_LEN); 15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_rsc) 15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key->key_rsc, key_rsc, WPA_KEY_RSC_LEN); 15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde && !encr) { 1512807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt os_memcpy(key_data, kde, kde_len); 1513807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (mic_len == 24) 1514807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt WPA_PUT_BE16(key192->key_data_length, kde_len); 1515807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt else 1516807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt WPA_PUT_BE16(key->key_data_length, kde_len); 15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (encr && kde) { 15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_zalloc(key_data_len); 15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(hdr); 15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, kde, kde_len); 15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += kde_len; 15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pad_len) 15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 0xdd; 15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data", 15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf, key_data_len); 15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || 1533f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN || 15346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_key_mgmt_suite_b(sm->wpa_key_mgmt) || 15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt version == WPA_KEY_INFO_TYPE_AES_128_CMAC) { 1536807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len, 1537807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt (key_data_len - 8) / 8, buf, key_data)) { 15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(hdr); 15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1542807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (mic_len == 24) 1543807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt WPA_PUT_BE16(key192->key_data_length, 1544807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt key_data_len); 1545807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt else 1546807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt WPA_PUT_BE16(key->key_data_length, 1547807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt key_data_len); 1548d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#ifndef CONFIG_NO_RC4 1549807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt } else if (sm->PTK.kek_len == 16) { 15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ek[32]; 15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key->key_iv, 15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group->Counter + WPA_NONCE_LEN - 16, 16); 15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(sm->group->Counter, WPA_NONCE_LEN); 15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ek, key->key_iv, 16); 1555807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt os_memcpy(ek + 16, sm->PTK.kek, sm->PTK.kek_len); 1556807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt os_memcpy(key_data, buf, key_data_len); 1557807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt rc4_skip(ek, 32, 256, key_data, key_data_len); 1558807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (mic_len == 24) 1559807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt WPA_PUT_BE16(key192->key_data_length, 1560807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt key_data_len); 1561807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt else 1562807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt WPA_PUT_BE16(key->key_data_length, 1563807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt key_data_len); 1564d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* CONFIG_NO_RC4 */ 1565807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt } else { 1566807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt os_free(hdr); 1567807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt os_free(buf); 1568807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt return; 15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_info & WPA_KEY_INFO_MIC) { 1574807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt u8 *key_mic; 1575807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->PTK_valid) { 15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, 15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PTK not valid when sending EAPOL-Key " 15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "frame"); 15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(hdr); 15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1583807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 1584807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt key_mic = key192->key_mic; /* same offset for key and key192 */ 1585807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_eapol_key_mic(sm->PTK.kck, sm->PTK.kck_len, 1586807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt sm->wpa_key_mgmt, version, 1587807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt (u8 *) hdr, len, key_mic); 158851b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt#ifdef CONFIG_TESTING_OPTIONS 158951b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt if (!pairwise && 15907832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt wpa_auth->conf.corrupt_gtk_rekey_mic_probability > 0.0 && 159151b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt drand48() < 159251b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt wpa_auth->conf.corrupt_gtk_rekey_mic_probability) { 159351b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 159451b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt "Corrupting group EAPOL-Key Key MIC"); 1595807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt key_mic[0]++; 159651b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt } 159751b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt#endif /* CONFIG_TESTING_OPTIONS */ 15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, 16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1); 16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_send_eapol(wpa_auth, sm->addr, (u8 *) hdr, len, 16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pairwise_set); 16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(hdr); 16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_send_eapol(struct wpa_authenticator *wpa_auth, 16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm, int key_info, 16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *key_rsc, const u8 *nonce, 16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *kde, size_t kde_len, 16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int keyidx, int encr) 16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int timeout_ms; 16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE; 16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ctr; 16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len, 16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keyidx, encr, 0); 16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctr = pairwise ? sm->TimeoutCtr : sm->GTimeoutCtr; 16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ctr == 1 && wpa_auth->conf.tx_status) 16261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt timeout_ms = pairwise ? eapol_key_timeout_first : 16271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eapol_key_timeout_first_group; 16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeout_ms = eapol_key_timeout_subseq; 16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pairwise && ctr == 1 && !(key_info & WPA_KEY_INFO_MIC)) 16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pending_1_of_4_timeout = 1; 16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Use EAPOL-Key timeout of %u ms (retry " 16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "counter %d)", timeout_ms, ctr); 16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000, 16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_send_eapol_timeout, wpa_auth, sm); 16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_verify_key_mic(int akmp, struct wpa_ptk *PTK, u8 *data, 16406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt size_t data_len) 16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee802_1x_hdr *hdr; 16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_key *key; 1644807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt struct wpa_eapol_key_192 *key192; 16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info; 16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 1647807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; 1648807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt size_t mic_len = wpa_mic_len(akmp); 16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data_len < sizeof(*hdr) + sizeof(*key)) 16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct ieee802_1x_hdr *) data; 16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = (struct wpa_eapol_key *) (hdr + 1); 1655807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt key192 = (struct wpa_eapol_key_192 *) (hdr + 1); 16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = WPA_GET_BE16(key->key_info); 1657807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt os_memcpy(mic, key192->key_mic, mic_len); 1658807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt os_memset(key192->key_mic, 0, mic_len); 1659807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (wpa_eapol_key_mic(PTK->kck, PTK->kck_len, akmp, 1660807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt key_info & WPA_KEY_INFO_TYPE_MASK, 1661807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt data, data_len, key192->key_mic) || 1662807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt os_memcmp_const(mic, key192->key_mic, mic_len) != 0) 16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 1664807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt os_memcpy(key192->key_mic, mic, mic_len); 16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_remove_ptk(struct wpa_state_machine *sm) 16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PTK_valid = FALSE; 16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&sm->PTK, 0, sizeof(sm->PTK)); 16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, NULL, 0); 16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pairwise_set = FALSE; 16758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); 16768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1679d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtint wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) 16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int remove_ptk = 1; 16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "event %d notification", event); 16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (event) { 16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_AUTH: 16916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_MESH 16926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* PTKs are derived through AMPE */ 16936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (wpa_auth_start_ampe(sm->wpa_auth, sm->addr)) { 16946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* not mesh */ 16956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 16966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 16976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 16986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_MESH */ 16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_ASSOC: 17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_DEAUTH: 17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_DISASSOC: 17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->DeauthenticationRequest = TRUE; 17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_REAUTH: 17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_REAUTH_EAPOL: 17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->started) { 17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * When using WPS, we may end up here if the STA 17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * manages to re-associate without the previous STA 17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * entry getting removed. Consequently, we need to make 17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * sure that the WPA state machines gets initialized 17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * properly at this point. 17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA state machine had not been " 17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "started - initialize now"); 17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->started = 1; 17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->Init = TRUE; 17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_step(sm) == 1) 17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; /* should not really happen */ 17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->Init = FALSE; 17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->AuthenticationRequest = TRUE; 17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->GUpdateStationKeys) { 17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Reauthentication cancels the pending group key 17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * update for this STA. 17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group->GKeyDoneStations--; 17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GUpdateStationKeys = FALSE; 17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PtkGroupInit = TRUE; 17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ReAuthenticationRequest = TRUE; 17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_ASSOC_FT: 17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "FT: Retry PTK configuration " 17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "after association"); 17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ft_install_ptk(sm); 17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Using FT protocol, not WPA auth state machine */ 17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ft_completed = 1; 17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_IEEE80211R */ 17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ft_completed = 0; 17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->mgmt_frame_prot && event == WPA_AUTH) 17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt remove_ptk = 0; 17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (remove_ptk) { 17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PTK_valid = FALSE; 17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&sm->PTK, 0, sizeof(sm->PTK)); 17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (event != WPA_REAUTH_EAPOL) 17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_remove_ptk(sm); 17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1767d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (sm->in_step_loop) { 1768d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt /* 1769d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * wpa_sm_step() is already running - avoid recursive call to 1770d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * it by making the existing loop process the new update. 1771d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt */ 1772d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt sm->changed = TRUE; 1773d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return 0; 1774d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_sm_step(sm); 17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, INITIALIZE) 17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, INITIALIZE, wpa_ptk); 17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->Init) { 17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Init flag is not cleared here, so avoid busy 17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * loop by claiming nothing changed. */ 17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->changed = FALSE; 17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->keycount = 0; 17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->GUpdateStationKeys) 17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group->GKeyDoneStations--; 17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GUpdateStationKeys = FALSE; 17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA) 17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PInitAKeys = FALSE; 17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (1 /* Unicast cipher supported AND (ESS OR ((IBSS or WDS) and 17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Local AA > Remote AA)) */) { 17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->Pair = TRUE; 17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 0); 17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_remove_ptk(sm); 18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 0); 18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutCtr = 0; 18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { 18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, 18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_EAPOL_authorized, 0); 18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, DISCONNECT) 18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, DISCONNECT, wpa_ptk); 18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->Disconnect = FALSE; 18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sta_disconnect(sm->wpa_auth, sm->addr); 18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, DISCONNECTED) 18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, DISCONNECTED, wpa_ptk); 18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->DeauthenticationRequest = FALSE; 18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, AUTHENTICATION) 18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, AUTHENTICATION, wpa_ptk); 18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&sm->PTK, 0, sizeof(sm->PTK)); 18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PTK_valid = FALSE; 18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portControl_Auto, 18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1); 18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 1); 18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->AuthenticationRequest = FALSE; 18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1836c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic void wpa_group_ensure_init(struct wpa_authenticator *wpa_auth, 1837c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct wpa_group *group) 18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1839c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (group->first_sta_seen) 1840c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return; 18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * System has run bit further than at the time hostapd was started 18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * potentially very early during boot up. This provides better chances 18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * of collecting more randomness on embedded systems. Re-initialize the 18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * GMK and Counter here to improve their strength if there was not 18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * enough entropy available immediately after system startup. 18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Re-initialize GMK/Counter on first " 18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "station"); 18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_pool_ready() != 1) { 18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "WPA: Not enough entropy in random pool " 18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "to proceed - reject first 4-way handshake"); 18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->reject_4way_hs_for_entropy = TRUE; 1854c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } else { 1855c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt group->first_sta_seen = TRUE; 1856c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt group->reject_4way_hs_for_entropy = FALSE; 18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1858c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 1859d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0 || 1860d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_gtk_update(wpa_auth, group) < 0 || 1861d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_group_config_group_keys(wpa_auth, group) < 0) { 1862d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_INFO, "WPA: GMK/GTK setup failed"); 1863d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt group->first_sta_seen = FALSE; 1864d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt group->reject_4way_hs_for_entropy = TRUE; 1865d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, AUTHENTICATION2) 18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, AUTHENTICATION2, wpa_ptk); 18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1873c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_group_ensure_init(sm->wpa_auth, sm->group); 1874444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt sm->ReAuthenticationRequest = FALSE; 18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 187604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* 187704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * Definition of ANonce selection in IEEE Std 802.11i-2004 is somewhat 187804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * ambiguous. The Authenticator state machine uses a counter that is 187904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * incremented by one for each 4-way handshake. However, the security 188004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * analysis of 4-way handshake points out that unpredictable nonces 188104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * help in preventing precomputation attacks. Instead of the state 188204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * machine definition, use an unpredictable nonce value here to provide 188304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * stronger protection against potential precomputation attacks. 188404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt */ 188504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) { 188604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_ERROR, "WPA: Failed to get random data for " 188704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "ANonce."); 1888444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt sm->Disconnect = TRUE; 188904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 189004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Assign ANonce", sm->ANonce, 18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_NONCE_LEN); 18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* IEEE 802.11i does not clear TimeoutCtr here, but this is more 18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * logical place than INITIALIZE since AUTHENTICATION2 can be 18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * re-entered on ReAuthenticationRequest without going through 18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * INITIALIZE. */ 18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutCtr = 0; 18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, INITPMK) 19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 msk[2 * PMK_LEN]; 19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len = 2 * PMK_LEN; 19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, INITPMK, wpa_ptk); 19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->xxkey_len = 0; 19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pmksa) { 19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: PMK from PMKSA cache"); 1912d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len); 1913d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt sm->pmk_len = sm->pmksa->pmk_len; 19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (wpa_auth_get_msk(sm->wpa_auth, sm->addr, msk, &len) == 0) { 1915d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt unsigned int pmk_len; 1916d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1917d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (sm->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) 1918d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt pmk_len = PMK_LEN_SUITE_B_192; 1919d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt else 1920d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt pmk_len = PMK_LEN; 19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: PMK from EAPOL state machine " 1922d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt "(MSK len=%lu PMK len=%u)", (unsigned long) len, 1923d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt pmk_len); 1924d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (len < pmk_len) { 1925d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_DEBUG, 1926d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt "WPA: MSK not long enough (%u) to create PMK (%u)", 1927d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt (unsigned int) len, (unsigned int) pmk_len); 1928d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt sm->Disconnect = TRUE; 1929d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return; 1930d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1931d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt os_memcpy(sm->PMK, msk, pmk_len); 1932d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt sm->pmk_len = pmk_len; 19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len >= 2 * PMK_LEN) { 19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->xxkey, msk + PMK_LEN, PMK_LEN); 19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->xxkey_len = PMK_LEN; 19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1940807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Could not get PMK, get_msk: %p", 1941807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt sm->wpa_auth->cb.get_msk); 1942216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt sm->Disconnect = TRUE; 1943216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt return; 19448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1945216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt os_memset(msk, 0, sizeof(msk)); 19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->req_replay_counter_used = 0; 19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* IEEE 802.11i does not set keyRun to FALSE, but not doing this 19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * will break reauthentication since EAPOL state machines may not be 19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * get into AUTHENTICATING state that clears keyRun before WPA state 19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * machine enters AUTHENTICATION2 state and goes immediately to INITPMK 19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * state and takes PMK from the previously used AAA Key. This will 19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eventually fail in 4-Way Handshake because Supplicant uses PMK 19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * derived from the new AAA Key. Setting keyRun = FALSE here seems to 19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * be good workaround for this issue. */ 19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun, 0); 19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, INITPSK) 19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *psk; 19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk); 1964391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL); 19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (psk) { 19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->PMK, psk, PMK_LEN); 1967d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt sm->pmk_len = PMK_LEN; 19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->xxkey, psk, PMK_LEN); 19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->xxkey_len = PMK_LEN; 19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->req_replay_counter_used = 0; 19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, PTKSTART) 19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 buf[2 + RSN_SELECTOR_LEN + PMKID_LEN], *pmkid = NULL; 19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t pmkid_len = 0; 19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, PTKSTART, wpa_ptk); 19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PTKRequest = FALSE; 19848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutEvt = FALSE; 19856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sm->alt_snonce_valid = FALSE; 19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutCtr++; 19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->TimeoutCtr > (int) dot11RSNAConfigPairwiseUpdateCount) { 19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No point in sending the EAPOL-Key - we will disconnect 19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * immediately following this. */ 19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "sending 1/4 msg of 4-Way Handshake"); 19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO: Could add PMKID even with WPA2-PSK, but only if there is only 19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * one possible PSK for this STA. 19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA2 && 2001f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) && 2002f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN) { 20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmkid = buf; 20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN; 20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmkid[0] = WLAN_EID_VENDOR_SPECIFIC; 20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN; 20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(&pmkid[2], RSN_KEY_DATA_PMKID); 20086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (sm->pmksa) { 20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN], 20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmksa->pmkid, PMKID_LEN); 20116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else if (wpa_key_mgmt_suite_b(sm->wpa_key_mgmt)) { 20126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* No KCK available to derive PMKID */ 20136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt pmkid = NULL; 20146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else { 20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Calculate PMKID since no PMKSA cache entry was 20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * available with pre-calculated PMKID. 20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2019d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt rsn_pmkid(sm->PMK, sm->pmk_len, sm->wpa_auth->addr, 20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->addr, &pmkid[2 + RSN_SELECTOR_LEN], 20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_key_mgmt_sha256(sm->wpa_key_mgmt)); 20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_send_eapol(sm->wpa_auth, sm, 20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL, 20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ANonce, pmkid, pmkid_len, 0, 0); 20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce, 2031d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt const u8 *pmk, unsigned int pmk_len, 2032d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct wpa_ptk *ptk) 20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) 2036807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt return wpa_auth_derive_ptk_ft(sm, pmk, ptk); 20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2039d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion", 2040807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce, 2041807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt ptk, sm->wpa_key_mgmt, sm->pairwise); 20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, PTKCALCNEGOTIATING) 20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ptk PTK; 2048dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt int ok = 0, psk_found = 0; 20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pmk = NULL; 2050d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt unsigned int pmk_len; 20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk); 20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->EAPOLKeyReceived = FALSE; 2054c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sm->update_snonce = FALSE; 20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* WPA with IEEE 802.1X: use the derived PMK from EAP 20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA-PSK: iterate through possible PSKs and select the one matching 20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the packet */ 20598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (;;) { 20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { 2061391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, 2062391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt sm->p2p_dev_addr, pmk); 20638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmk == NULL) 20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2065dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt psk_found = 1; 2066d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt pmk_len = PMK_LEN; 2067d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } else { 20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmk = sm->PMK; 2069d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt pmk_len = sm->pmk_len; 2070d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2072d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK); 20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (wpa_verify_key_mic(sm->wpa_key_mgmt, &PTK, 20756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sm->last_rx_eapol_key, 20768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->last_rx_eapol_key_len) == 0) { 20778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ok = 1; 20788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 20798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) 20828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 20838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ok) { 20868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "invalid MIC in msg 2/4 of 4-Way Handshake"); 2088dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt if (psk_found) 2089dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt wpa_auth_psk_failure_report(sm->wpa_auth, sm->addr); 20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { 20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Verify that PMKR1Name from EAPOL-Key message 2/4 matches 20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * with the value we derived. 20988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2099c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(sm->sup_pmk_r1_name, sm->pmk_r1_name, 2100c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt WPA_PMK_NAME_LEN) != 0) { 21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PMKR1Name mismatch in FT 4-way " 21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "handshake"); 21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from " 21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Supplicant", 21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->sup_pmk_r1_name, WPA_PMK_NAME_LEN); 21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name", 21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmk_r1_name, WPA_PMK_NAME_LEN); 21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 21138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pending_1_of_4_timeout = 0; 21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm); 21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { 21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* PSK may have changed from the previous choice, so update 21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * state machine data based on whatever PSK was selected here. 21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->PMK, pmk, PMK_LEN); 2122d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt sm->pmk_len = PMK_LEN; 21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->MICVerified = TRUE; 21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&sm->PTK, &PTK, sizeof(PTK)); 21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PTK_valid = TRUE; 21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 21308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21328d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, PTKCALCNEGOTIATING2) 21338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 21348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING2, wpa_ptk); 21358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutCtr = 0; 21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee80211w_kde_len(struct wpa_state_machine *sm) 21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->mgmt_frame_prot) { 2144b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt size_t len; 2145b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); 2146b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN + len; 21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) 21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 21558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_igtk_kde igtk; 21568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *gsm = sm->group; 215768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt u8 rsc[WPA_KEY_RSC_LEN]; 2158b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); 21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->mgmt_frame_prot) 21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt igtk.keyid[0] = gsm->GN_igtk; 21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt igtk.keyid[1] = 0; 21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE || 216668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, rsc) < 0) 21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(igtk.pn, 0, sizeof(igtk.pn)); 216868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt else 216968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt os_memcpy(igtk.pn, rsc, sizeof(igtk.pn)); 2170b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], len); 217161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->wpa_auth->conf.disable_gtk) { 217261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* 217361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Provide unique random IGTK to each STA to prevent use of 217461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * IGTK in the BSS. 217561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 2176b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (random_get_bytes(igtk.igtk, len) < 0) 217761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return pos; 217861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 21798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK, 2180b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt (const u8 *) &igtk, WPA_IGTK_KDE_PREFIX_LEN + len, 2181b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt NULL, 0); 21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_IEEE80211W */ 21878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee80211w_kde_len(struct wpa_state_machine *sm) 21898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 21908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) 21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22028d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, PTKINITNEGOTIATING) 22038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 220461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos, dummy_gtk[32]; 22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t gtk_len, kde_len; 22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *gsm = sm->group; 22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *wpa_ie; 22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int wpa_ie_len, secure, keyidx, encr = 0; 22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk); 22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutEvt = FALSE; 22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutCtr++; 22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->TimeoutCtr > (int) dot11RSNAConfigPairwiseUpdateCount) { 22158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No point in sending the EAPOL-Key - we will disconnect 22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * immediately following this. */ 22178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 22188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE], 22218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GTK[GN], IGTK, [FTIE], [TIE * 2]) 22228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 22238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(rsc, 0, WPA_KEY_RSC_LEN); 22248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc); 22258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */ 22268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ie = sm->wpa_auth->wpa_ie; 22278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ie_len = sm->wpa_auth->wpa_ie_len; 22288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA && 22298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) && 22308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ie_len > wpa_ie[1] + 2 && wpa_ie[0] == WLAN_EID_RSN) { 22316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* WPA-only STA, remove RSN IE and possible MDIE */ 22328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ie = wpa_ie + wpa_ie[1] + 2; 22336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN) 22346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_ie = wpa_ie + wpa_ie[1] + 2; 22358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ie_len = wpa_ie[1] + 2; 22368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 22388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "sending 3/4 msg of 4-Way Handshake"); 22398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA2) { 22408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* WPA2 send GTK in the 4-way handshake */ 22418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt secure = 1; 22428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gtk = gsm->GTK[gsm->GN - 1]; 22438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gtk_len = gsm->GTK_len; 224461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->wpa_auth->conf.disable_gtk) { 224561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* 224661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Provide unique random GTK to each STA to prevent use 224761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * of GTK in the BSS. 224861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 224961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (random_get_bytes(dummy_gtk, gtk_len) < 0) 225061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 225161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gtk = dummy_gtk; 225261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keyidx = gsm->GN; 22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _rsc = rsc; 22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encr = 1; 22568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 22578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* WPA does not include GTK in msg 3/4 */ 22588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt secure = 0; 22598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gtk = NULL; 22608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gtk_len = 0; 22618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keyidx = 0; 22628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _rsc = NULL; 22631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (sm->rx_eapol_key_secure) { 22641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 22651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * It looks like Windows 7 supplicant tries to use 22661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Secure bit in msg 2/4 after having reported Michael 22671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * MIC failure and it then rejects the 4-way handshake 22681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * if msg 3/4 does not set Secure bit. Work around this 22691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * by setting the Secure bit here even in the case of 22701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * WPA if the supplicant used it first. 22711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 22721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 22731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "STA used Secure bit in WPA msg 2/4 - " 22741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "set Secure for 3/4 as workaround"); 22751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt secure = 1; 22761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 22778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len = wpa_ie_len + ieee80211w_kde_len(sm); 22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gtk) 22818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len; 22828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { 22848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */ 22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len += 300; /* FTIE + 2 * TIE */ 22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 2288cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_P2P 2289cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (WPA_GET_BE32(sm->ip_addr) > 0) 2290cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt kde_len += 2 + RSN_SELECTOR_LEN + 3 * 4; 2291cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_P2P */ 22928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde = os_malloc(kde_len); 22938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde == NULL) 22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = kde; 22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, wpa_ie, wpa_ie_len); 22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += wpa_ie_len; 22998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 23008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { 230155840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt int res; 230255840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt size_t elen; 230355840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt 230455840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt elen = pos - kde; 230555840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name); 23068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 23078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "FT: Failed to insert " 23088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PMKR1Name into RSN IE in EAPOL-Key data"); 23098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(kde); 23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 23118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 231255840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt pos -= wpa_ie_len; 231355840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt pos += elen; 23148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 23168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gtk) { 23178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hdr[2]; 23188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr[0] = keyidx & 0x03; 23198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr[1] = 0; 23208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, 23218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gtk, gtk_len); 23228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = ieee80211w_kde_add(sm, pos); 23248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 23268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { 23278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 23288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_auth_config *conf; 23298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf = &sm->wpa_auth->conf; 233155840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt if (sm->assoc_resp_ftie && 233255840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) { 233355840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt os_memcpy(pos, sm->assoc_resp_ftie, 233455840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt 2 + sm->assoc_resp_ftie[1]); 233555840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt res = 2 + sm->assoc_resp_ftie[1]; 233655840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt } else { 233755840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt res = wpa_write_ftie(conf, conf->r0_key_holder, 233855840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt conf->r0_key_holder_len, 233955840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt NULL, NULL, pos, 234055840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt kde + kde_len - pos, 234155840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt NULL, 0); 234255840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt } 23438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 23448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE " 23458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "into EAPOL-Key Key Data"); 23468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(kde); 23478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 23488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += res; 23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TIE[ReassociationDeadline] (TU) */ 23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = WLAN_EID_TIMEOUT_INTERVAL; 23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 5; 23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE; 23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE32(pos, conf->reassociation_deadline); 23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 4; 23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TIE[KeyLifetime] (seconds) */ 23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = WLAN_EID_TIMEOUT_INTERVAL; 23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 5; 23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = WLAN_TIMEOUT_KEY_LIFETIME; 23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE32(pos, conf->r0_key_lifetime * 60); 23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 4; 23648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 2366cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_P2P 2367cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (WPA_GET_BE32(sm->ip_addr) > 0) { 2368cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt u8 addr[3 * 4]; 2369cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt os_memcpy(addr, sm->ip_addr, 4); 2370cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt os_memcpy(addr + 4, sm->wpa_auth->conf.ip_addr_mask, 4); 2371cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt os_memcpy(addr + 8, sm->wpa_auth->conf.ip_addr_go, 4); 2372cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt pos = wpa_add_kde(pos, WFA_KEY_DATA_IP_ADDR_ALLOC, 2373cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt addr, sizeof(addr), NULL, 0); 2374cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 2375cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_P2P */ 23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_send_eapol(sm->wpa_auth, sm, 23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (secure ? WPA_KEY_INFO_SECURE : 0) | WPA_KEY_INFO_MIC | 23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL | 23808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_KEY_TYPE, 23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _rsc, sm->ANonce, kde, pos - kde, keyidx, encr); 23828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(kde); 23838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK, PTKINITDONE) 23878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk); 23898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->EAPOLKeyReceived = FALSE; 23908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->Pair) { 23914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise); 23924530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt int klen = wpa_cipher_key_len(sm->pairwise); 23938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, 2394807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt sm->PTK.tk, klen)) { 23958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sta_disconnect(sm->wpa_auth, sm->addr); 23968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 23978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ 23998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pairwise_set = TRUE; 24008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_auth->conf.wpa_ptk_rekey) { 24028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); 24038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(sm->wpa_auth->conf. 24048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ptk_rekey, 0, wpa_rekey_ptk, 24058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_auth, sm); 24068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { 24098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, 24108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_EAPOL_authorized, 1); 24118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (0 /* IBSS == TRUE */) { 24158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->keycount++; 24168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->keycount == 2) { 24178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, 24188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_EAPOL_portValid, 1); 24198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 24218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 24228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1); 24238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyAvailable, 0); 24258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyDone, 1); 24268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA) 24278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PInitAKeys = TRUE; 24288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 24298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->has_GTK = TRUE; 24308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, 24318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pairwise key handshake completed (%s)", 24328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN"); 24338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 24358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ft_push_pmk_r1(sm->wpa_auth, sm->addr); 24368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 24378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 24388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24408d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STEP(WPA_PTK) 24418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 24428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_authenticator *wpa_auth = sm->wpa_auth; 24438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->Init) 24458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, INITIALIZE); 24468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->Disconnect 24478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* || FIX: dot11RSNAConfigSALifetime timeout */) { 24488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, 24498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA_PTK: sm->Disconnect"); 24508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, DISCONNECT); 24518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->DeauthenticationRequest) 24538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, DISCONNECTED); 24548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->AuthenticationRequest) 24558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, AUTHENTICATION); 24568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->ReAuthenticationRequest) 24578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, AUTHENTICATION2); 24588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->PTKRequest) 24598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKSTART); 24608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else switch (sm->wpa_ptk_state) { 24618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_INITIALIZE: 24628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 24638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_DISCONNECT: 24648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, DISCONNECTED); 24658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 24668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_DISCONNECTED: 24678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, INITIALIZE); 24688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 24698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_AUTHENTICATION: 24708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, AUTHENTICATION2); 24718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 24728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_AUTHENTICATION2: 24738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) && 24748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_get_eapol(sm->wpa_auth, sm->addr, 24758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_EAPOL_keyRun) > 0) 24768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, INITPMK); 24778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) 24788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: && 802.1X::keyRun */) 24798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, INITPSK); 24808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 24818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_INITPMK: 24828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_get_eapol(sm->wpa_auth, sm->addr, 24838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_EAPOL_keyAvailable) > 0) 24848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKSTART); 24858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 24868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNA4WayHandshakeFailures++; 24878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, 24888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "INITPMK - keyAvailable = false"); 24898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, DISCONNECT); 24908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 24928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_INITPSK: 2493391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, 2494391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt NULL)) 24958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKSTART); 24968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 24978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, 24988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "no PSK configured for the STA"); 24998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNA4WayHandshakeFailures++; 25008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, DISCONNECT); 25018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 25038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_PTKSTART: 25048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && 25058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->EAPOLKeyPairwise) 25068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); 25078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->TimeoutCtr > 25088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) dot11RSNAConfigPairwiseUpdateCount) { 25098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNA4WayHandshakeFailures++; 25108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 25118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PTKSTART: Retry limit %d reached", 25128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dot11RSNAConfigPairwiseUpdateCount); 25138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, DISCONNECT); 25148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (sm->TimeoutEvt) 25158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKSTART); 25168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 25178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_PTKCALCNEGOTIATING: 25188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->MICVerified) 25198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING2); 25208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && 25218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->EAPOLKeyPairwise) 25228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); 25238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->TimeoutEvt) 25248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKSTART); 25258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 25268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_PTKCALCNEGOTIATING2: 25278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKINITNEGOTIATING); 25288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 25298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_PTKINITNEGOTIATING: 2530c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (sm->update_snonce) 2531c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); 2532c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && 2533c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sm->EAPOLKeyPairwise && sm->MICVerified) 25348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKINITDONE); 25358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->TimeoutCtr > 25368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) dot11RSNAConfigPairwiseUpdateCount) { 25378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNA4WayHandshakeFailures++; 25388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 25398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PTKINITNEGOTIATING: Retry limit %d " 25408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "reached", 25418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dot11RSNAConfigPairwiseUpdateCount); 25428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, DISCONNECT); 25438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (sm->TimeoutEvt) 25448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK, PTKINITNEGOTIATING); 25458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 25468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_PTKINITDONE: 25478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 25488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 25508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25528d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK_GROUP, IDLE) 25538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 25548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK_GROUP, IDLE, wpa_ptk_group); 25558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->Init) { 25568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Init flag is not cleared here, so avoid busy 25578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * loop by claiming nothing changed. */ 25588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->changed = FALSE; 25598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GTimeoutCtr = 0; 25618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 25628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25648d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) 25658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 25668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rsc[WPA_KEY_RSC_LEN]; 25678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *gsm = sm->group; 25686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *kde; 25696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u8 *kde_buf = NULL, *pos, hdr[2]; 25708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t kde_len; 257161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 *gtk, dummy_gtk[32]; 25728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group); 25748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GTimeoutCtr++; 25768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->GTimeoutCtr > (int) dot11RSNAConfigGroupUpdateCount) { 25778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No point in sending the EAPOL-Key - we will disconnect 25788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * immediately following this. */ 25798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 25808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA) 25838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PInitAKeys = FALSE; 25848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->TimeoutEvt = FALSE; 25858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */ 25868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(rsc, 0, WPA_KEY_RSC_LEN); 25878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gsm->wpa_group_state == WPA_GROUP_SETKEYSDONE) 25888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc); 25898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 25908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "sending 1/2 msg of Group Key Handshake"); 25918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 259261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gtk = gsm->GTK[gsm->GN - 1]; 259361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->wpa_auth->conf.disable_gtk) { 259461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* 259561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Provide unique random GTK to each STA to prevent use 259661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * of GTK in the BSS. 259761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 259861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (random_get_bytes(dummy_gtk, gsm->GTK_len) < 0) 259961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 260061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gtk = dummy_gtk; 260161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 26028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa == WPA_VERSION_WPA2) { 26038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len + 26048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee80211w_kde_len(sm); 26056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt kde_buf = os_malloc(kde_len); 26066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (kde_buf == NULL) 26078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 26088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt kde = pos = kde_buf; 26108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr[0] = gsm->GN & 0x03; 26118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr[1] = 0; 26128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, 261361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gtk, gsm->GTK_len); 26148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = ieee80211w_kde_add(sm, pos); 26156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt kde_len = pos - kde; 26168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 261761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt kde = gtk; 26186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt kde_len = gsm->GTK_len; 26198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 26208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_send_eapol(sm->wpa_auth, sm, 26228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC | 26238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_INFO_ACK | 26248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0), 26256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt rsc, gsm->GNonce, kde, kde_len, gsm->GN, 1); 26266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 26276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_free(kde_buf); 26288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26318d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED) 26328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK_GROUP, REKEYESTABLISHED, wpa_ptk_group); 26348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->EAPOLKeyReceived = FALSE; 26358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->GUpdateStationKeys) 26368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group->GKeyDoneStations--; 26378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GUpdateStationKeys = FALSE; 26388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GTimeoutCtr = 0; 26398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */ 26408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, 26418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "group key handshake completed (%s)", 26428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN"); 26438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->has_GTK = TRUE; 26448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26478d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(WPA_PTK_GROUP, KEYERROR) 26488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTRY_MA(WPA_PTK_GROUP, KEYERROR, wpa_ptk_group); 26508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->GUpdateStationKeys) 26518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group->GKeyDoneStations--; 26528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GUpdateStationKeys = FALSE; 26538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->Disconnect = TRUE; 26548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26578d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STEP(WPA_PTK_GROUP) 26588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->Init || sm->PtkGroupInit) { 26608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK_GROUP, IDLE); 26618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->PtkGroupInit = FALSE; 26628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else switch (sm->wpa_ptk_group_state) { 26638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_GROUP_IDLE: 26648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->GUpdateStationKeys || 26658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (sm->wpa == WPA_VERSION_WPA && sm->PInitAKeys)) 26668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING); 26678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 26688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_GROUP_REKEYNEGOTIATING: 26698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && 26708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !sm->EAPOLKeyPairwise && sm->MICVerified) 26718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK_GROUP, REKEYESTABLISHED); 26728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->GTimeoutCtr > 26738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) dot11RSNAConfigGroupUpdateCount) 26748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK_GROUP, KEYERROR); 26758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->TimeoutEvt) 26768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING); 26778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 26788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_GROUP_KEYERROR: 26798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK_GROUP, IDLE); 26808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 26818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_PTK_GROUP_REKEYESTABLISHED: 26828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_ENTER(WPA_PTK_GROUP, IDLE); 26838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 26848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 26858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_gtk_update(struct wpa_authenticator *wpa_auth, 26898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group) 26908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 26928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); 26948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(group->Counter, WPA_NONCE_LEN); 26958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_gmk_to_gtk(group->GMK, "Group key expansion", 26968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->addr, group->GNonce, 26978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTK[group->GN - 1], group->GTK_len) < 0) 26988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 26998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "GTK", 27008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTK[group->GN - 1], group->GTK_len); 27018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 27038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) { 2704b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt size_t len; 2705b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher); 27068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); 27078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inc_byte_array(group->Counter, WPA_NONCE_LEN); 27088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion", 27098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->addr, group->GNonce, 2710b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt group->IGTK[group->GN_igtk - 4], len) < 0) 27118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 27128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IGTK", 2713b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt group->IGTK[group->GN_igtk - 4], len); 27148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 27158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 27168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 27188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 27198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth, 27228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group) 27238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 27248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " 27258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "GTK_INIT (VLAN-ID %d)", group->vlan_id); 27268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->changed = FALSE; /* GInit is not cleared here; avoid loop */ 27278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->wpa_group_state = WPA_GROUP_GTK_INIT; 27288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* GTK[0..N] = 0 */ 27308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(group->GTK, 0, sizeof(group->GTK)); 27318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GN = 1; 27328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GM = 2; 27338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 27348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GN_igtk = 4; 27358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GM_igtk = 5; 27368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 27378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* GTK[GN] = CalcGTK() */ 27388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_gtk_update(wpa_auth, group); 27398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 27408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx) 27438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 274461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (ctx != NULL && ctx != sm->group) 274561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 274661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 27478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) { 27488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 27498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Not in PTKINITDONE; skip Group Key update"); 27508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GUpdateStationKeys = FALSE; 27518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 27528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 27538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->GUpdateStationKeys) { 27548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 27558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This should not really happen, so add a debug log entry. 27568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Since we clear the GKeyDoneStations before the loop, the 27578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * station needs to be counted here anyway. 27588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 27598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 27608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "GUpdateStationKeys was already set when " 27618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "marking station for GTK rekeying"); 27628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 27638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2764a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt /* Do not rekey GTK/IGTK when STA is in WNM-Sleep Mode */ 276561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->is_wnmsleep) 276661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 276761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 27688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group->GKeyDoneStations++; 27698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->GUpdateStationKeys = TRUE; 27708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_step(sm); 27728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 27738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 27748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2776a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#ifdef CONFIG_WNM 2777a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt/* update GTK when exiting WNM-Sleep Mode */ 277861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm) 277961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 2780fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (sm == NULL || sm->is_wnmsleep) 278161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 278261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 278361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_group_update_sta(sm, NULL); 278461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 278561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 278661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 278761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag) 278861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 2789fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (sm) 2790fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt sm->is_wnmsleep = !!flag; 279161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 279261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 279361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 279461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos) 279561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 279661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_group *gsm = sm->group; 2797a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt u8 *start = pos; 279861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 279961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* 2800a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * GTK subelement: 280161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] | 2802a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Key[5..32] 280361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 2804a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *pos++ = WNM_SLEEP_SUBELEM_GTK; 2805a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *pos++ = 11 + gsm->GTK_len; 280661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* Key ID in B0-B1 of Key Info */ 2807a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt WPA_PUT_LE16(pos, gsm->GN & 0x03); 2808a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos += 2; 2809a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *pos++ = gsm->GTK_len; 2810a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, pos) != 0) 281161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 2812a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos += 8; 2813a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt os_memcpy(pos, gsm->GTK[gsm->GN - 1], gsm->GTK_len); 2814a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos += gsm->GTK_len; 281561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2816a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_printf(MSG_DEBUG, "WNM: GTK Key ID %u in WNM-Sleep Mode exit", 2817a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt gsm->GN); 2818a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WNM: GTK in WNM-Sleep Mode exit", 281961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gsm->GTK[gsm->GN - 1], gsm->GTK_len); 282061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2821a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return pos - start; 282261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 282361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 282461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 282561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_IEEE80211W 282661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos) 282761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 282861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_group *gsm = sm->group; 2829a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt u8 *start = pos; 2830b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); 283161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2832a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt /* 2833a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * IGTK subelement: 2834a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16] 2835a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt */ 2836a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *pos++ = WNM_SLEEP_SUBELEM_IGTK; 2837b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt *pos++ = 2 + 6 + len; 2838a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt WPA_PUT_LE16(pos, gsm->GN_igtk); 2839a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos += 2; 2840a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos) != 0) 284161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 2842a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos += 6; 284361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2844b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], len); 2845b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt pos += len; 284661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2847a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_printf(MSG_DEBUG, "WNM: IGTK Key ID %u in WNM-Sleep Mode exit", 2848a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt gsm->GN_igtk); 2849a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WNM: IGTK in WNM-Sleep Mode exit", 2850b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt gsm->IGTK[gsm->GN_igtk - 4], len); 285161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2852a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return pos - start; 285361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 285461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 2855a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#endif /* CONFIG_WNM */ 285661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 285761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 28588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_group_setkeys(struct wpa_authenticator *wpa_auth, 28598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group) 28608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 28618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tmp; 28628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " 28648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SETKEYS (VLAN-ID %d)", group->vlan_id); 28658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->changed = TRUE; 28668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->wpa_group_state = WPA_GROUP_SETKEYS; 28678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTKReKey = FALSE; 28688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = group->GM; 28698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GM = group->GN; 28708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GN = tmp; 28718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 28728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = group->GM_igtk; 28738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GM_igtk = group->GN_igtk; 28748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GN_igtk = tmp; 28758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 28768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* "GKeyDoneStations = GNoStations" is done in more robust way by 28778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * counting the STAs that are marked with GUpdateStationKeys instead of 28788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * including all STAs that could be in not-yet-completed state. */ 28798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_gtk_update(wpa_auth, group); 28808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group->GKeyDoneStations) { 28828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "wpa_group_setkeys: Unexpected " 28838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "GKeyDoneStations=%d when starting new GTK rekey", 28848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GKeyDoneStations); 28858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GKeyDoneStations = 0; 28868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 288761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_auth_for_each_sta(wpa_auth, wpa_group_update_sta, group); 28888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "wpa_group_setkeys: GKeyDoneStations=%d", 28898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GKeyDoneStations); 28908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 28918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth, 28948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group) 28958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 28968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 28978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_set_key(wpa_auth, group->vlan_id, 28994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_cipher_to_alg(wpa_auth->conf.wpa_group), 29008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt broadcast_ether_addr, group->GN, 29018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTK[group->GN - 1], group->GTK_len) < 0) 29028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 29038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 2905b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) { 2906b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt enum wpa_alg alg; 2907b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt size_t len; 2908b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 2909b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt alg = wpa_cipher_to_alg(wpa_auth->conf.group_mgmt_cipher); 2910b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher); 2911b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 2912b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (ret == 0 && 2913b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt wpa_auth_set_key(wpa_auth, group->vlan_id, alg, 2914b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt broadcast_ether_addr, group->GN_igtk, 2915b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt group->IGTK[group->GN_igtk - 4], len) < 0) 2916b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt ret = -1; 2917b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt } 29188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 29198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 29218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 29228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2924fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidtstatic int wpa_group_disconnect_cb(struct wpa_state_machine *sm, void *ctx) 2925fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt{ 2926fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (sm->group == ctx) { 2927fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Mark STA " MACSTR 2928fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt " for discconnection due to fatal failure", 2929fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt MAC2STR(sm->addr)); 2930fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt sm->Disconnect = TRUE; 2931fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 2932fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 2933fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return 0; 2934fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt} 2935fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 2936fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 2937fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidtstatic void wpa_group_fatal_failure(struct wpa_authenticator *wpa_auth, 2938fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct wpa_group *group) 2939fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt{ 2940fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: group state machine entering state FATAL_FAILURE"); 2941fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt group->changed = TRUE; 2942fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt group->wpa_group_state = WPA_GROUP_FATAL_FAILURE; 2943fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_auth_for_each_sta(wpa_auth, wpa_group_disconnect_cb, group); 2944fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt} 2945fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 2946fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 29478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth, 29488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group) 29498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 29508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " 29518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SETKEYSDONE (VLAN-ID %d)", group->vlan_id); 29528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->changed = TRUE; 29538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->wpa_group_state = WPA_GROUP_SETKEYSDONE; 29548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2955fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (wpa_group_config_group_keys(wpa_auth, group) < 0) { 2956fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_group_fatal_failure(wpa_auth, group); 29578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2958fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 29598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 29618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 29628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_group_sm_step(struct wpa_authenticator *wpa_auth, 29658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group) 29668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 29678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group->GInit) { 29688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_gtk_init(wpa_auth, group); 2969fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } else if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) { 2970fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt /* Do not allow group operations */ 29718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (group->wpa_group_state == WPA_GROUP_GTK_INIT && 29728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTKAuthenticator) { 29738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_setkeysdone(wpa_auth, group); 29748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (group->wpa_group_state == WPA_GROUP_SETKEYSDONE && 29758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GTKReKey) { 29768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_setkeys(wpa_auth, group); 29778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (group->wpa_group_state == WPA_GROUP_SETKEYS) { 29788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group->GKeyDoneStations == 0) 29798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_setkeysdone(wpa_auth, group); 29808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (group->GTKReKey) 29818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_setkeys(wpa_auth, group); 29828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 29838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 29848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_sm_step(struct wpa_state_machine *sm) 29878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 29888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 29898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 29908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->in_step_loop) { 29928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* This should not happen, but if it does, make sure we do not 29938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * end up freeing the state machine too early by exiting the 29948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * recursive call. */ 29958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "WPA: wpa_sm_step() called recursively"); 29968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 29978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 29988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->in_step_loop = 1; 30008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt do { 30018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pending_deinit) 30028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 30038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->changed = FALSE; 30058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_auth->group->changed = FALSE; 30068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_STEP_RUN(WPA_PTK); 30088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pending_deinit) 30098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 30108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SM_STEP_RUN(WPA_PTK_GROUP); 30118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pending_deinit) 30128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 30138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_group_sm_step(sm->wpa_auth, sm->group); 30148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } while (sm->changed || sm->wpa_auth->group->changed); 30158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->in_step_loop = 0; 30168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pending_deinit) { 30188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Completing pending STA state " 30198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "machine deinit for " MACSTR, MAC2STR(sm->addr)); 30208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_free_sta_sm(sm); 30218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 30228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 30238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 30248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 30258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx) 30288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 30298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm = eloop_ctx; 30308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_step(sm); 30318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 30328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_auth_sm_notify(struct wpa_state_machine *sm) 30358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 30368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 30378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 30388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL); 30398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 30408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_gtk_rekey(struct wpa_authenticator *wpa_auth) 30438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 30448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tmp, i; 30458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group; 30468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL) 30488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 30498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = wpa_auth->group; 30518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < 2; i++) { 30538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = group->GM; 30548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GM = group->GN; 30558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GN = tmp; 30568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 30578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = group->GM_igtk; 30588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GM_igtk = group->GN_igtk; 30598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->GN_igtk = tmp; 30608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 30618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_gtk_update(wpa_auth, group); 30621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_group_config_group_keys(wpa_auth, group); 30638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 30648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 30658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30671d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidtstatic const char * wpa_bool_txt(int val) 30688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 30691d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt return val ? "TRUE" : "FALSE"; 30708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 30718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RSN_SUITE "%02x-%02x-%02x-%d" 30748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RSN_SUITE_ARG(s) \ 30758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff 30768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen) 30788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 30798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int len = 0, ret; 30808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char pmkid_txt[PMKID_LEN * 2 + 1]; 30818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_RSN_PREAUTH 30828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const int preauth = 1; 30838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_RSN_PREAUTH */ 30848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const int preauth = 0; 30858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_RSN_PREAUTH */ 30868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL) 30888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 30898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, 30918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAOptionImplemented=TRUE\n" 30928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAPreauthenticationImplemented=%s\n" 30938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAEnabled=%s\n" 30948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAPreauthenticationEnabled=%s\n", 30958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_bool_txt(preauth), 30968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_bool_txt(wpa_auth->conf.wpa & WPA_PROTO_RSN), 30978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_bool_txt(wpa_auth->conf.rsn_preauth)); 30986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(buflen - len, ret)) 30998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 31008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 31018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt), 31038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNAPMKIDUsed, PMKID_LEN); 31048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf( 31068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf + len, buflen - len, 31078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigVersion=%u\n" 31088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigPairwiseKeysSupported=9999\n" 31098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: dot11RSNAConfigGroupCipher */ 31108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: dot11RSNAConfigGroupRekeyMethod */ 31118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: dot11RSNAConfigGroupRekeyTime */ 31128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: dot11RSNAConfigGroupRekeyPackets */ 31138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigGroupRekeyStrict=%u\n" 31148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigGroupUpdateCount=%u\n" 31158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigPairwiseUpdateCount=%u\n" 31168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigGroupCipherSize=%u\n" 31178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigPMKLifetime=%u\n" 31188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigPMKReauthThreshold=%u\n" 31198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigNumberOfPTKSAReplayCounters=0\n" 31208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigSATimeout=%u\n" 31218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n" 31228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n" 31238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n" 31248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAPMKIDUsed=%s\n" 31258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n" 31268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n" 31278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n" 31288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNATKIPCounterMeasuresInvoked=%u\n" 31298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNA4WayHandshakeFailures=%u\n" 31308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n", 31318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_VERSION, 31328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !!wpa_auth->conf.wpa_strict_rekey, 31338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dot11RSNAConfigGroupUpdateCount, 31348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dot11RSNAConfigPairwiseUpdateCount, 31354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_cipher_key_len(wpa_auth->conf.wpa_group) * 8, 31368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dot11RSNAConfigPMKLifetime, 31378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dot11RSNAConfigPMKReauthThreshold, 31388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dot11RSNAConfigSATimeout, 31398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteSelected), 31408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherSelected), 31418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherSelected), 31428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmkid_txt, 31438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteRequested), 31448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherRequested), 31458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherRequested), 31468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNATKIPCounterMeasuresInvoked, 31478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNA4WayHandshakeFailures); 31486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(buflen - len, ret)) 31498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 31508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 31518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot11RSNAConfigPairwiseCiphersTable */ 31538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot11RSNAConfigAuthenticationSuitesTable */ 31548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Private MIB */ 31568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, "hostapdWPAGroupState=%d\n", 31578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->group->wpa_group_state); 31586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(buflen - len, ret)) 31598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 31608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 31618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 31638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 31648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen) 31678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 31688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int len = 0, ret; 31698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 pairwise = 0; 31708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 31728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 31738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: FF-FF-FF-FF-FF-FF entry for broadcast/multicast stats */ 31758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* dot11RSNAStatsEntry */ 31778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt pairwise = wpa_cipher_to_suite(sm->wpa == WPA_VERSION_WPA2 ? 31794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt WPA_PROTO_RSN : WPA_PROTO_WPA, 31804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->pairwise); 31814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (pairwise == 0) 31828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 31838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf( 31858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf + len, buflen - len, 31868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot11RSNAStatsIndex */ 31878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAStatsSTAAddress=" MACSTR "\n" 31888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAStatsVersion=1\n" 31898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAStatsSelectedPairwiseCipher=" RSN_SUITE "\n" 31908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot11RSNAStatsTKIPICVErrors */ 31918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAStatsTKIPLocalMICFailures=%u\n" 31928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot11RSNAStatsTKIPRemoteMICFailures=%u\n" 31938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot11RSNAStatsCCMPReplays */ 31948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot11RSNAStatsCCMPDecryptErrors */ 31958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot11RSNAStatsTKIPReplays */, 31968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(sm->addr), 31978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SUITE_ARG(pairwise), 31988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAStatsTKIPLocalMICFailures, 31998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAStatsTKIPRemoteMICFailures); 32006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(buflen - len, ret)) 32018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 32028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 32038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Private MIB */ 32058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, 32068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "hostapdWPAPTKState=%d\n" 32078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "hostapdWPAPTKGroupState=%d\n", 32088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ptk_state, 32098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ptk_group_state); 32106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(buflen - len, ret)) 32118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 32128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 32138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 32158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 32168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth) 32198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 32208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth) 32218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNATKIPCounterMeasuresInvoked++; 32228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 32238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_pairwise_set(struct wpa_state_machine *sm) 32268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 32278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm && sm->pairwise_set; 32288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 32298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_get_pairwise(struct wpa_state_machine *sm) 32328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 32338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->pairwise; 32348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 32358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm) 32388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 32398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 32408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 32418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->wpa_key_mgmt; 32428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 32438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_sta_wpa_version(struct wpa_state_machine *sm) 32468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 32478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 32488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 32498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->wpa; 32508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 32518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm, 32548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *entry) 32558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 32568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL || sm->pmksa != entry) 32578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 32588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmksa = NULL; 32598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 32608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 32618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct rsn_pmksa_cache_entry * 32648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_auth_sta_get_pmksa(struct wpa_state_machine *sm) 32658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 32668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm ? sm->pmksa : NULL; 32678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 32688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm) 32718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 32728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm) 32738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot11RSNAStatsTKIPLocalMICFailures++; 32748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 32758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, size_t *len) 32788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 32798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL) 32808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 32818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = wpa_auth->wpa_ie_len; 32828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_auth->wpa_ie; 32838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 32848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk, 3287d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt unsigned int pmk_len, 32888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int session_timeout, struct eapol_state_machine *eapol) 32898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3290c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt if (sm == NULL || sm->wpa != WPA_VERSION_WPA2 || 3291c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt sm->wpa_auth->conf.disable_pmksa_caching) 32928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 32938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3294d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (sm->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) { 3295d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (pmk_len > PMK_LEN_SUITE_B_192) 3296d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt pmk_len = PMK_LEN_SUITE_B_192; 3297d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } else if (pmk_len > PMK_LEN) { 3298d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt pmk_len = PMK_LEN; 3299d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 3300d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 330157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, pmk_len, NULL, 3302807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt sm->PTK.kck, sm->PTK.kck_len, 33038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_auth->addr, sm->addr, session_timeout, 33048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol, sm->wpa_key_mgmt)) 33058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 33068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 33088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 33098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth, 33128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pmk, size_t len, const u8 *sta_addr, 33138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int session_timeout, 33148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *eapol) 33158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 33168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL) 33178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 33188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 331957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, len, NULL, 33206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NULL, 0, 33216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_auth->addr, 33228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta_addr, session_timeout, eapol, 33238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_MGMT_IEEE8021X)) 33248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 33258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 33278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 33288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr, 333157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt const u8 *pmk, const u8 *pmkid) 33326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 33336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (wpa_auth->conf.disable_pmksa_caching) 33346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 33356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 333657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, PMK_LEN, pmkid, 33376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NULL, 0, 33386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_auth->addr, addr, 0, NULL, 33396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WPA_KEY_MGMT_SAE)) 33406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 33416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 33426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 33436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 33446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 33456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3346f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidtvoid wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth, 3347f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt const u8 *sta_addr) 3348f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt{ 3349f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt struct rsn_pmksa_cache_entry *pmksa; 3350f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt 3351f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt if (wpa_auth == NULL || wpa_auth->pmksa == NULL) 3352f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt return; 3353f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, NULL); 3354f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt if (pmksa) { 3355f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Remove PMKSA cache entry for " 3356f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt MACSTR " based on request", MAC2STR(sta_addr)); 3357f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt pmksa_cache_free_entry(wpa_auth->pmksa, pmksa); 3358f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt } 3359f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt} 3360f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt 3361f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt 3362e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidtint wpa_auth_pmksa_list(struct wpa_authenticator *wpa_auth, char *buf, 3363e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt size_t len) 3364e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt{ 3365e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt if (!wpa_auth || !wpa_auth->pmksa) 3366e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt return 0; 3367e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt return pmksa_cache_auth_list(wpa_auth->pmksa, buf, len); 3368e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt} 3369e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt 3370e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt 3371e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidtvoid wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth) 3372e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt{ 3373e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt if (wpa_auth && wpa_auth->pmksa) 3374e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt pmksa_cache_auth_flush(wpa_auth->pmksa); 3375e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt} 3376e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt 3377e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt 3378e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidtstruct rsn_pmksa_cache_entry * 3379e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidtwpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr) 3380e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt{ 3381e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt if (!wpa_auth || !wpa_auth->pmksa) 3382e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt return NULL; 3383e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt return pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, NULL); 3384e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt} 3385e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt 3386e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt 3387e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidtvoid wpa_auth_pmksa_set_to_sm(struct rsn_pmksa_cache_entry *pmksa, 3388e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt struct wpa_state_machine *sm, 3389e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt struct wpa_authenticator *wpa_auth, 3390e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt u8 *pmkid, u8 *pmk) 3391e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt{ 3392e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt if (!sm) 3393e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt return; 3394e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt 3395e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt sm->pmksa = pmksa; 3396e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt os_memcpy(pmk, pmksa->pmk, PMK_LEN); 3397e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt os_memcpy(pmkid, pmksa->pmkid, PMKID_LEN); 3398e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmksa->pmkid, PMKID_LEN); 3399e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt} 3400e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt 3401e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt 34021d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt/* 34031d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt * Remove and free the group from wpa_authenticator. This is triggered by a 34041d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt * callback to make sure nobody is currently iterating the group list while it 34051d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt * gets modified. 34061d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt */ 34071d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidtstatic void wpa_group_free(struct wpa_authenticator *wpa_auth, 34081d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt struct wpa_group *group) 34091d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt{ 34101d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt struct wpa_group *prev = wpa_auth->group; 34111d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt 34121d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Remove group state machine for VLAN-ID %d", 34131d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt group->vlan_id); 34141d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt 34151d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt while (prev) { 34161d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt if (prev->next == group) { 34171d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt /* This never frees the special first group as needed */ 34181d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt prev->next = group->next; 34191d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt os_free(group); 34201d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt break; 34211d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt } 34221d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt prev = prev->next; 34231d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt } 34241d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt 34251d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt} 34261d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt 34271d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt 34281d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt/* Increase the reference counter for group */ 34291d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidtstatic void wpa_group_get(struct wpa_authenticator *wpa_auth, 34301d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt struct wpa_group *group) 34311d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt{ 34321d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt /* Skip the special first group */ 34331d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt if (wpa_auth->group == group) 34341d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt return; 34351d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt 34361d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt group->references++; 34371d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt} 34381d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt 34391d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt 34401d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt/* Decrease the reference counter and maybe free the group */ 34411d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidtstatic void wpa_group_put(struct wpa_authenticator *wpa_auth, 34421d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt struct wpa_group *group) 34431d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt{ 34441d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt /* Skip the special first group */ 34451d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt if (wpa_auth->group == group) 34461d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt return; 34471d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt 34481d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt group->references--; 34491d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt if (group->references) 34501d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt return; 34511d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt wpa_group_free(wpa_auth, group); 34521d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt} 34531d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt 34541d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt 34551d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt/* 34561d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt * Add a group that has its references counter set to zero. Caller needs to 34571d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt * call wpa_group_get() on the return value to mark the entry in use. 34581d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt */ 34598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_group * 34608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id) 34618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 34628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group; 34638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL || wpa_auth->group == NULL) 34658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 34668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Add group state machine for VLAN-ID %d", 34688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vlan_id); 34691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt group = wpa_group_init(wpa_auth, vlan_id, 0); 34708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group == NULL) 34718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 34728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group->next = wpa_auth->group->next; 34748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->group->next = group; 34758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return group; 34778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 34788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3480d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt/* 3481d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * Enforce that the group state machine for the VLAN is running, increase 3482d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * reference counter as interface is up. References might have been increased 3483d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * even if a negative value is returned. 3484d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * Returns: -1 on error (group missing, group already failed); otherwise, 0 3485d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt */ 3486d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtint wpa_auth_ensure_group(struct wpa_authenticator *wpa_auth, int vlan_id) 3487d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{ 3488d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct wpa_group *group; 3489d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 3490d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (wpa_auth == NULL) 3491d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return 0; 3492d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 3493d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt group = wpa_auth->group; 3494d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt while (group) { 3495d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (group->vlan_id == vlan_id) 3496d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt break; 3497d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt group = group->next; 3498d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 3499d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 3500d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (group == NULL) { 3501d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt group = wpa_auth_add_group(wpa_auth, vlan_id); 3502d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (group == NULL) 3503d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return -1; 3504d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 3505d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 3506d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_DEBUG, 3507d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt "WPA: Ensure group state machine running for VLAN ID %d", 3508d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt vlan_id); 3509d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 3510d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_group_get(wpa_auth, group); 3511d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt group->num_setup_iface++; 3512d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 3513d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) 3514d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return -1; 3515d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 3516d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return 0; 3517d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt} 3518d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 3519d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 3520d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt/* 3521d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * Decrease reference counter, expected to be zero afterwards. 3522d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * returns: -1 on error (group not found, group in fail state) 3523d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * -2 if wpa_group is still referenced 3524d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * 0 else 3525d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt */ 3526d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtint wpa_auth_release_group(struct wpa_authenticator *wpa_auth, int vlan_id) 3527d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{ 3528d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct wpa_group *group; 3529d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt int ret = 0; 3530d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 3531d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (wpa_auth == NULL) 3532d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return 0; 3533d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 3534d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt group = wpa_auth->group; 3535d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt while (group) { 3536d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (group->vlan_id == vlan_id) 3537d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt break; 3538d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt group = group->next; 3539d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 3540d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 3541d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (group == NULL) 3542d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return -1; 3543d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 3544d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_DEBUG, 3545d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt "WPA: Try stopping group state machine for VLAN ID %d", 3546d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt vlan_id); 3547d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 3548d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (group->num_setup_iface <= 0) { 3549d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_ERROR, 3550d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt "WPA: wpa_auth_release_group called more often than wpa_auth_ensure_group for VLAN ID %d, skipping.", 3551d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt vlan_id); 3552d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return -1; 3553d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 3554d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt group->num_setup_iface--; 3555d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 3556d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) 3557d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt ret = -1; 3558d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 3559d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (group->references > 1) { 3560d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_DEBUG, 3561d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt "WPA: Cannot stop group state machine for VLAN ID %d as references are still hold", 3562d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt vlan_id); 3563d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt ret = -2; 3564d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 3565d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 3566d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_group_put(wpa_auth, group); 3567d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 3568d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return ret; 3569d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt} 3570d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 3571d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 35728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id) 35738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 35748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_group *group; 35758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL || sm->wpa_auth == NULL) 35778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 35788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = sm->wpa_auth->group; 35808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (group) { 35818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group->vlan_id == vlan_id) 35828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 35838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = group->next; 35848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 35858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group == NULL) { 35878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = wpa_auth_add_group(sm->wpa_auth, vlan_id); 35888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group == NULL) 35898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 35908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 35918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->group == group) 35938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 35948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3595fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) 3596fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return -1; 3597fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 35988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR " to use group state " 35998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "machine for VLAN ID %d", MAC2STR(sm->addr), vlan_id); 36008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 36011d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt wpa_group_get(sm->wpa_auth, group); 36021d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt wpa_group_put(sm->wpa_auth, sm->group); 36038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->group = group; 36041d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt 36058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 36068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 36078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 36088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 36098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth, 36108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm, int ack) 36118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 36128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL || sm == NULL) 36138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 36148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key TX status for STA " MACSTR 36158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " ack=%d", MAC2STR(sm->addr), ack); 36168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pending_1_of_4_timeout && ack) { 36178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 36188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Some deployed supplicant implementations update their SNonce 36198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * for each EAPOL-Key 2/4 message even within the same 4-way 36208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * handshake and then fail to use the first SNonce when 36218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * deriving the PTK. This results in unsuccessful 4-way 36228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * handshake whenever the relatively short initial timeout is 36238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * reached and EAPOL-Key 1/4 is retransmitted. Try to work 36248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * around this by increasing the timeout now that we know that 36258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the station has received the frame. 36268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 36278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int timeout_ms = eapol_key_timeout_subseq; 36288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: Increase initial EAPOL-Key 1/4 " 36298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "timeout by %u ms because of acknowledged frame", 36308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeout_ms); 36318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm); 36328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(timeout_ms / 1000, 36338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (timeout_ms % 1000) * 1000, 36348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_send_eapol_timeout, wpa_auth, sm); 36358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 36368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3637d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 3638d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 3639d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtint wpa_auth_uses_sae(struct wpa_state_machine *sm) 3640d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt{ 3641d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (sm == NULL) 3642d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return 0; 3643d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return wpa_key_mgmt_sae(sm->wpa_key_mgmt); 3644d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt} 3645fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 3646fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 3647fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidtint wpa_auth_uses_ft_sae(struct wpa_state_machine *sm) 3648fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt{ 3649fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (sm == NULL) 3650fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return 0; 3651fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE; 3652fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt} 3653cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 3654cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 3655cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_P2P 3656cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtint wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr) 3657cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{ 3658cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (sm == NULL || WPA_GET_BE32(sm->ip_addr) == 0) 3659cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return -1; 3660cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt os_memcpy(addr, sm->ip_addr, 4); 3661cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return 0; 3662cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt} 3663cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_P2P */ 36642f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt 36652f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt 36662f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidtint wpa_auth_radius_das_disconnect_pmksa(struct wpa_authenticator *wpa_auth, 36672f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt struct radius_das_attrs *attr) 36682f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt{ 36692f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt return pmksa_cache_auth_radius_das_disconnect(wpa_auth->pmksa, attr); 36702f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt} 36717f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 36727f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 36737f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidtvoid wpa_auth_reconfig_group_keys(struct wpa_authenticator *wpa_auth) 36747f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt{ 36757f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt struct wpa_group *group; 36767f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 36777f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (!wpa_auth) 36787f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt return; 36797f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt for (group = wpa_auth->group; group; group = group->next) 36807f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_group_config_group_keys(wpa_auth, group); 36817f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt} 3682