1214501Srpaulo/* 2252726Srpaulo * IEEE 802.11 RSN / WPA Authenticator 3346981Scy * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi> 4214501Srpaulo * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7214501Srpaulo */ 8214501Srpaulo 9214501Srpaulo#include "utils/includes.h" 10214501Srpaulo 11214501Srpaulo#include "utils/common.h" 12214501Srpaulo#include "utils/eloop.h" 13214501Srpaulo#include "utils/state_machine.h" 14281806Srpaulo#include "utils/bitfield.h" 15214501Srpaulo#include "common/ieee802_11_defs.h" 16346981Scy#include "common/ocv.h" 17346981Scy#include "crypto/aes.h" 18214501Srpaulo#include "crypto/aes_wrap.h" 19346981Scy#include "crypto/aes_siv.h" 20214501Srpaulo#include "crypto/crypto.h" 21214501Srpaulo#include "crypto/sha1.h" 22214501Srpaulo#include "crypto/sha256.h" 23346981Scy#include "crypto/sha384.h" 24252726Srpaulo#include "crypto/random.h" 25214501Srpaulo#include "eapol_auth/eapol_auth_sm.h" 26346981Scy#include "drivers/driver.h" 27214501Srpaulo#include "ap_config.h" 28214501Srpaulo#include "ieee802_11.h" 29214501Srpaulo#include "wpa_auth.h" 30214501Srpaulo#include "pmksa_cache_auth.h" 31214501Srpaulo#include "wpa_auth_i.h" 32214501Srpaulo#include "wpa_auth_ie.h" 33214501Srpaulo 34214501Srpaulo#define STATE_MACHINE_DATA struct wpa_state_machine 35214501Srpaulo#define STATE_MACHINE_DEBUG_PREFIX "WPA" 36214501Srpaulo#define STATE_MACHINE_ADDR sm->addr 37214501Srpaulo 38214501Srpaulo 39214501Srpaulostatic void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx); 40214501Srpaulostatic int wpa_sm_step(struct wpa_state_machine *sm); 41346981Scystatic int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK, 42346981Scy u8 *data, size_t data_len); 43346981Scy#ifdef CONFIG_FILS 44346981Scystatic int wpa_aead_decrypt(struct wpa_state_machine *sm, struct wpa_ptk *ptk, 45346981Scy u8 *buf, size_t buf_len, u16 *_key_data_len); 46346981Scystatic struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm, 47346981Scy const struct wpabuf *hlp); 48346981Scy#endif /* CONFIG_FILS */ 49214501Srpaulostatic void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx); 50214501Srpaulostatic void wpa_group_sm_step(struct wpa_authenticator *wpa_auth, 51214501Srpaulo struct wpa_group *group); 52214501Srpaulostatic void wpa_request_new_ptk(struct wpa_state_machine *sm); 53214501Srpaulostatic int wpa_gtk_update(struct wpa_authenticator *wpa_auth, 54214501Srpaulo struct wpa_group *group); 55252726Srpaulostatic int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth, 56252726Srpaulo struct wpa_group *group); 57281806Srpaulostatic int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce, 58337817Scy const u8 *pmk, unsigned int pmk_len, 59337817Scy struct wpa_ptk *ptk); 60289549Srpaulostatic void wpa_group_free(struct wpa_authenticator *wpa_auth, 61289549Srpaulo struct wpa_group *group); 62289549Srpaulostatic void wpa_group_get(struct wpa_authenticator *wpa_auth, 63289549Srpaulo struct wpa_group *group); 64289549Srpaulostatic void wpa_group_put(struct wpa_authenticator *wpa_auth, 65289549Srpaulo struct wpa_group *group); 66346981Scystatic u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos); 67214501Srpaulo 68214501Srpaulostatic const u32 eapol_key_timeout_first = 100; /* ms */ 69214501Srpaulostatic const u32 eapol_key_timeout_subseq = 1000; /* ms */ 70252726Srpaulostatic const u32 eapol_key_timeout_first_group = 500; /* ms */ 71346981Scystatic const u32 eapol_key_timeout_no_retrans = 4000; /* ms */ 72214501Srpaulo 73214501Srpaulo/* TODO: make these configurable */ 74214501Srpaulostatic const int dot11RSNAConfigPMKLifetime = 43200; 75214501Srpaulostatic const int dot11RSNAConfigPMKReauthThreshold = 70; 76214501Srpaulostatic const int dot11RSNAConfigSATimeout = 60; 77214501Srpaulo 78214501Srpaulo 79252726Srpaulostatic inline int wpa_auth_mic_failure_report( 80214501Srpaulo struct wpa_authenticator *wpa_auth, const u8 *addr) 81214501Srpaulo{ 82346981Scy if (wpa_auth->cb->mic_failure_report) 83346981Scy return wpa_auth->cb->mic_failure_report(wpa_auth->cb_ctx, addr); 84252726Srpaulo return 0; 85214501Srpaulo} 86214501Srpaulo 87214501Srpaulo 88289549Srpaulostatic inline void wpa_auth_psk_failure_report( 89289549Srpaulo struct wpa_authenticator *wpa_auth, const u8 *addr) 90289549Srpaulo{ 91346981Scy if (wpa_auth->cb->psk_failure_report) 92346981Scy wpa_auth->cb->psk_failure_report(wpa_auth->cb_ctx, addr); 93289549Srpaulo} 94289549Srpaulo 95289549Srpaulo 96214501Srpaulostatic inline void wpa_auth_set_eapol(struct wpa_authenticator *wpa_auth, 97214501Srpaulo const u8 *addr, wpa_eapol_variable var, 98214501Srpaulo int value) 99214501Srpaulo{ 100346981Scy if (wpa_auth->cb->set_eapol) 101346981Scy wpa_auth->cb->set_eapol(wpa_auth->cb_ctx, addr, var, value); 102214501Srpaulo} 103214501Srpaulo 104214501Srpaulo 105214501Srpaulostatic inline int wpa_auth_get_eapol(struct wpa_authenticator *wpa_auth, 106214501Srpaulo const u8 *addr, wpa_eapol_variable var) 107214501Srpaulo{ 108346981Scy if (wpa_auth->cb->get_eapol == NULL) 109214501Srpaulo return -1; 110346981Scy return wpa_auth->cb->get_eapol(wpa_auth->cb_ctx, addr, var); 111214501Srpaulo} 112214501Srpaulo 113214501Srpaulo 114214501Srpaulostatic inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth, 115281806Srpaulo const u8 *addr, 116281806Srpaulo const u8 *p2p_dev_addr, 117346981Scy const u8 *prev_psk, size_t *psk_len, 118346981Scy int *vlan_id) 119214501Srpaulo{ 120346981Scy if (wpa_auth->cb->get_psk == NULL) 121214501Srpaulo return NULL; 122346981Scy return wpa_auth->cb->get_psk(wpa_auth->cb_ctx, addr, p2p_dev_addr, 123346981Scy prev_psk, psk_len, vlan_id); 124214501Srpaulo} 125214501Srpaulo 126214501Srpaulo 127214501Srpaulostatic inline int wpa_auth_get_msk(struct wpa_authenticator *wpa_auth, 128214501Srpaulo const u8 *addr, u8 *msk, size_t *len) 129214501Srpaulo{ 130346981Scy if (wpa_auth->cb->get_msk == NULL) 131214501Srpaulo return -1; 132346981Scy return wpa_auth->cb->get_msk(wpa_auth->cb_ctx, addr, msk, len); 133214501Srpaulo} 134214501Srpaulo 135214501Srpaulo 136214501Srpaulostatic inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, 137214501Srpaulo int vlan_id, 138214501Srpaulo enum wpa_alg alg, const u8 *addr, int idx, 139214501Srpaulo u8 *key, size_t key_len) 140214501Srpaulo{ 141346981Scy if (wpa_auth->cb->set_key == NULL) 142214501Srpaulo return -1; 143346981Scy return wpa_auth->cb->set_key(wpa_auth->cb_ctx, vlan_id, alg, addr, idx, 144346981Scy key, key_len); 145214501Srpaulo} 146214501Srpaulo 147214501Srpaulo 148214501Srpaulostatic inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth, 149214501Srpaulo const u8 *addr, int idx, u8 *seq) 150214501Srpaulo{ 151346981Scy if (wpa_auth->cb->get_seqnum == NULL) 152214501Srpaulo return -1; 153346981Scy return wpa_auth->cb->get_seqnum(wpa_auth->cb_ctx, addr, idx, seq); 154214501Srpaulo} 155214501Srpaulo 156214501Srpaulo 157214501Srpaulostatic inline int 158214501Srpaulowpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr, 159214501Srpaulo const u8 *data, size_t data_len, int encrypt) 160214501Srpaulo{ 161346981Scy if (wpa_auth->cb->send_eapol == NULL) 162214501Srpaulo return -1; 163346981Scy return wpa_auth->cb->send_eapol(wpa_auth->cb_ctx, addr, data, data_len, 164346981Scy encrypt); 165214501Srpaulo} 166214501Srpaulo 167214501Srpaulo 168281806Srpaulo#ifdef CONFIG_MESH 169281806Srpaulostatic inline int wpa_auth_start_ampe(struct wpa_authenticator *wpa_auth, 170281806Srpaulo const u8 *addr) 171281806Srpaulo{ 172346981Scy if (wpa_auth->cb->start_ampe == NULL) 173281806Srpaulo return -1; 174346981Scy return wpa_auth->cb->start_ampe(wpa_auth->cb_ctx, addr); 175281806Srpaulo} 176281806Srpaulo#endif /* CONFIG_MESH */ 177281806Srpaulo 178281806Srpaulo 179214501Srpauloint wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth, 180214501Srpaulo int (*cb)(struct wpa_state_machine *sm, void *ctx), 181214501Srpaulo void *cb_ctx) 182214501Srpaulo{ 183346981Scy if (wpa_auth->cb->for_each_sta == NULL) 184214501Srpaulo return 0; 185346981Scy return wpa_auth->cb->for_each_sta(wpa_auth->cb_ctx, cb, cb_ctx); 186214501Srpaulo} 187214501Srpaulo 188214501Srpaulo 189214501Srpauloint wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth, 190214501Srpaulo int (*cb)(struct wpa_authenticator *a, void *ctx), 191214501Srpaulo void *cb_ctx) 192214501Srpaulo{ 193346981Scy if (wpa_auth->cb->for_each_auth == NULL) 194214501Srpaulo return 0; 195346981Scy return wpa_auth->cb->for_each_auth(wpa_auth->cb_ctx, cb, cb_ctx); 196214501Srpaulo} 197214501Srpaulo 198214501Srpaulo 199214501Srpaulovoid wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr, 200214501Srpaulo logger_level level, const char *txt) 201214501Srpaulo{ 202346981Scy if (wpa_auth->cb->logger == NULL) 203214501Srpaulo return; 204346981Scy wpa_auth->cb->logger(wpa_auth->cb_ctx, addr, level, txt); 205214501Srpaulo} 206214501Srpaulo 207214501Srpaulo 208214501Srpaulovoid wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr, 209214501Srpaulo logger_level level, const char *fmt, ...) 210214501Srpaulo{ 211214501Srpaulo char *format; 212214501Srpaulo int maxlen; 213214501Srpaulo va_list ap; 214214501Srpaulo 215346981Scy if (wpa_auth->cb->logger == NULL) 216214501Srpaulo return; 217214501Srpaulo 218214501Srpaulo maxlen = os_strlen(fmt) + 100; 219214501Srpaulo format = os_malloc(maxlen); 220214501Srpaulo if (!format) 221214501Srpaulo return; 222214501Srpaulo 223214501Srpaulo va_start(ap, fmt); 224214501Srpaulo vsnprintf(format, maxlen, fmt, ap); 225214501Srpaulo va_end(ap); 226214501Srpaulo 227214501Srpaulo wpa_auth_logger(wpa_auth, addr, level, format); 228214501Srpaulo 229214501Srpaulo os_free(format); 230214501Srpaulo} 231214501Srpaulo 232214501Srpaulo 233214501Srpaulostatic void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth, 234346981Scy const u8 *addr, u16 reason) 235214501Srpaulo{ 236346981Scy if (wpa_auth->cb->disconnect == NULL) 237214501Srpaulo return; 238346981Scy wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR " (reason %u)", 239346981Scy MAC2STR(addr), reason); 240346981Scy wpa_auth->cb->disconnect(wpa_auth->cb_ctx, addr, reason); 241214501Srpaulo} 242214501Srpaulo 243214501Srpaulo 244346981Scy#ifdef CONFIG_OCV 245346981Scystatic int wpa_channel_info(struct wpa_authenticator *wpa_auth, 246346981Scy struct wpa_channel_info *ci) 247214501Srpaulo{ 248346981Scy if (!wpa_auth->cb->channel_info) 249346981Scy return -1; 250346981Scy return wpa_auth->cb->channel_info(wpa_auth->cb_ctx, ci); 251214501Srpaulo} 252346981Scy#endif /* CONFIG_OCV */ 253214501Srpaulo 254214501Srpaulo 255346981Scystatic int wpa_auth_update_vlan(struct wpa_authenticator *wpa_auth, 256346981Scy const u8 *addr, int vlan_id) 257346981Scy{ 258346981Scy if (!wpa_auth->cb->update_vlan) 259346981Scy return -1; 260346981Scy return wpa_auth->cb->update_vlan(wpa_auth->cb_ctx, addr, vlan_id); 261346981Scy} 262346981Scy 263346981Scy 264214501Srpaulostatic void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx) 265214501Srpaulo{ 266214501Srpaulo struct wpa_authenticator *wpa_auth = eloop_ctx; 267214501Srpaulo 268252726Srpaulo if (random_get_bytes(wpa_auth->group->GMK, WPA_GMK_LEN)) { 269214501Srpaulo wpa_printf(MSG_ERROR, "Failed to get random data for WPA " 270214501Srpaulo "initialization."); 271214501Srpaulo } else { 272214501Srpaulo wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "GMK rekeyd"); 273252726Srpaulo wpa_hexdump_key(MSG_DEBUG, "GMK", 274252726Srpaulo wpa_auth->group->GMK, WPA_GMK_LEN); 275214501Srpaulo } 276214501Srpaulo 277214501Srpaulo if (wpa_auth->conf.wpa_gmk_rekey) { 278214501Srpaulo eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0, 279214501Srpaulo wpa_rekey_gmk, wpa_auth, NULL); 280214501Srpaulo } 281214501Srpaulo} 282214501Srpaulo 283214501Srpaulo 284214501Srpaulostatic void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx) 285214501Srpaulo{ 286214501Srpaulo struct wpa_authenticator *wpa_auth = eloop_ctx; 287289549Srpaulo struct wpa_group *group, *next; 288214501Srpaulo 289214501Srpaulo wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "rekeying GTK"); 290289549Srpaulo group = wpa_auth->group; 291289549Srpaulo while (group) { 292289549Srpaulo wpa_group_get(wpa_auth, group); 293289549Srpaulo 294214501Srpaulo group->GTKReKey = TRUE; 295214501Srpaulo do { 296214501Srpaulo group->changed = FALSE; 297214501Srpaulo wpa_group_sm_step(wpa_auth, group); 298214501Srpaulo } while (group->changed); 299289549Srpaulo 300289549Srpaulo next = group->next; 301289549Srpaulo wpa_group_put(wpa_auth, group); 302289549Srpaulo group = next; 303214501Srpaulo } 304214501Srpaulo 305214501Srpaulo if (wpa_auth->conf.wpa_group_rekey) { 306214501Srpaulo eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, 307214501Srpaulo 0, wpa_rekey_gtk, wpa_auth, NULL); 308214501Srpaulo } 309214501Srpaulo} 310214501Srpaulo 311214501Srpaulo 312214501Srpaulostatic void wpa_rekey_ptk(void *eloop_ctx, void *timeout_ctx) 313214501Srpaulo{ 314214501Srpaulo struct wpa_authenticator *wpa_auth = eloop_ctx; 315214501Srpaulo struct wpa_state_machine *sm = timeout_ctx; 316214501Srpaulo 317214501Srpaulo wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "rekeying PTK"); 318214501Srpaulo wpa_request_new_ptk(sm); 319214501Srpaulo wpa_sm_step(sm); 320214501Srpaulo} 321214501Srpaulo 322214501Srpaulo 323346981Scyvoid wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm) 324346981Scy{ 325346981Scy if (sm && sm->wpa_auth->conf.wpa_ptk_rekey) { 326346981Scy wpa_printf(MSG_DEBUG, "WPA: Start PTK rekeying timer for " 327346981Scy MACSTR " (%d seconds)", MAC2STR(sm->addr), 328346981Scy sm->wpa_auth->conf.wpa_ptk_rekey); 329346981Scy eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); 330346981Scy eloop_register_timeout(sm->wpa_auth->conf.wpa_ptk_rekey, 0, 331346981Scy wpa_rekey_ptk, sm->wpa_auth, sm); 332346981Scy } 333346981Scy} 334346981Scy 335346981Scy 336214501Srpaulostatic int wpa_auth_pmksa_clear_cb(struct wpa_state_machine *sm, void *ctx) 337214501Srpaulo{ 338214501Srpaulo if (sm->pmksa == ctx) 339214501Srpaulo sm->pmksa = NULL; 340214501Srpaulo return 0; 341214501Srpaulo} 342214501Srpaulo 343214501Srpaulo 344214501Srpaulostatic void wpa_auth_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry, 345214501Srpaulo void *ctx) 346214501Srpaulo{ 347214501Srpaulo struct wpa_authenticator *wpa_auth = ctx; 348214501Srpaulo wpa_auth_for_each_sta(wpa_auth, wpa_auth_pmksa_clear_cb, entry); 349214501Srpaulo} 350214501Srpaulo 351214501Srpaulo 352252726Srpaulostatic int wpa_group_init_gmk_and_counter(struct wpa_authenticator *wpa_auth, 353252726Srpaulo struct wpa_group *group) 354214501Srpaulo{ 355281806Srpaulo u8 buf[ETH_ALEN + 8 + sizeof(unsigned long)]; 356252726Srpaulo u8 rkey[32]; 357281806Srpaulo unsigned long ptr; 358252726Srpaulo 359252726Srpaulo if (random_get_bytes(group->GMK, WPA_GMK_LEN) < 0) 360252726Srpaulo return -1; 361252726Srpaulo wpa_hexdump_key(MSG_DEBUG, "GMK", group->GMK, WPA_GMK_LEN); 362252726Srpaulo 363252726Srpaulo /* 364252726Srpaulo * Counter = PRF-256(Random number, "Init Counter", 365252726Srpaulo * Local MAC Address || Time) 366252726Srpaulo */ 367252726Srpaulo os_memcpy(buf, wpa_auth->addr, ETH_ALEN); 368252726Srpaulo wpa_get_ntp_timestamp(buf + ETH_ALEN); 369281806Srpaulo ptr = (unsigned long) group; 370281806Srpaulo os_memcpy(buf + ETH_ALEN + 8, &ptr, sizeof(ptr)); 371346981Scy#ifdef TEST_FUZZ 372346981Scy os_memset(buf + ETH_ALEN, 0xab, 8); 373346981Scy os_memset(buf + ETH_ALEN + 8, 0xcd, sizeof(ptr)); 374346981Scy#endif /* TEST_FUZZ */ 375252726Srpaulo if (random_get_bytes(rkey, sizeof(rkey)) < 0) 376252726Srpaulo return -1; 377252726Srpaulo 378252726Srpaulo if (sha1_prf(rkey, sizeof(rkey), "Init Counter", buf, sizeof(buf), 379252726Srpaulo group->Counter, WPA_NONCE_LEN) < 0) 380252726Srpaulo return -1; 381252726Srpaulo wpa_hexdump_key(MSG_DEBUG, "Key Counter", 382252726Srpaulo group->Counter, WPA_NONCE_LEN); 383252726Srpaulo 384252726Srpaulo return 0; 385214501Srpaulo} 386214501Srpaulo 387214501Srpaulo 388214501Srpaulostatic struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth, 389252726Srpaulo int vlan_id, int delay_init) 390214501Srpaulo{ 391214501Srpaulo struct wpa_group *group; 392214501Srpaulo 393214501Srpaulo group = os_zalloc(sizeof(struct wpa_group)); 394214501Srpaulo if (group == NULL) 395214501Srpaulo return NULL; 396214501Srpaulo 397214501Srpaulo group->GTKAuthenticator = TRUE; 398214501Srpaulo group->vlan_id = vlan_id; 399252726Srpaulo group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group); 400214501Srpaulo 401252726Srpaulo if (random_pool_ready() != 1) { 402252726Srpaulo wpa_printf(MSG_INFO, "WPA: Not enough entropy in random pool " 403252726Srpaulo "for secure operations - update keys later when " 404252726Srpaulo "the first station connects"); 405252726Srpaulo } 406214501Srpaulo 407252726Srpaulo /* 408252726Srpaulo * Set initial GMK/Counter value here. The actual values that will be 409252726Srpaulo * used in negotiations will be set once the first station tries to 410252726Srpaulo * connect. This allows more time for collecting additional randomness 411252726Srpaulo * on embedded devices. 412214501Srpaulo */ 413252726Srpaulo if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0) { 414214501Srpaulo wpa_printf(MSG_ERROR, "Failed to get random data for WPA " 415214501Srpaulo "initialization."); 416214501Srpaulo os_free(group); 417214501Srpaulo return NULL; 418214501Srpaulo } 419214501Srpaulo 420214501Srpaulo group->GInit = TRUE; 421252726Srpaulo if (delay_init) { 422252726Srpaulo wpa_printf(MSG_DEBUG, "WPA: Delay group state machine start " 423252726Srpaulo "until Beacon frames have been configured"); 424252726Srpaulo /* Initialization is completed in wpa_init_keys(). */ 425252726Srpaulo } else { 426252726Srpaulo wpa_group_sm_step(wpa_auth, group); 427252726Srpaulo group->GInit = FALSE; 428252726Srpaulo wpa_group_sm_step(wpa_auth, group); 429252726Srpaulo } 430214501Srpaulo 431214501Srpaulo return group; 432214501Srpaulo} 433214501Srpaulo 434214501Srpaulo 435214501Srpaulo/** 436214501Srpaulo * wpa_init - Initialize WPA authenticator 437214501Srpaulo * @addr: Authenticator address 438214501Srpaulo * @conf: Configuration for WPA authenticator 439214501Srpaulo * @cb: Callback functions for WPA authenticator 440214501Srpaulo * Returns: Pointer to WPA authenticator data or %NULL on failure 441214501Srpaulo */ 442214501Srpaulostruct wpa_authenticator * wpa_init(const u8 *addr, 443214501Srpaulo struct wpa_auth_config *conf, 444346981Scy const struct wpa_auth_callbacks *cb, 445346981Scy void *cb_ctx) 446214501Srpaulo{ 447214501Srpaulo struct wpa_authenticator *wpa_auth; 448214501Srpaulo 449214501Srpaulo wpa_auth = os_zalloc(sizeof(struct wpa_authenticator)); 450214501Srpaulo if (wpa_auth == NULL) 451214501Srpaulo return NULL; 452214501Srpaulo os_memcpy(wpa_auth->addr, addr, ETH_ALEN); 453214501Srpaulo os_memcpy(&wpa_auth->conf, conf, sizeof(*conf)); 454346981Scy wpa_auth->cb = cb; 455346981Scy wpa_auth->cb_ctx = cb_ctx; 456214501Srpaulo 457214501Srpaulo if (wpa_auth_gen_wpa_ie(wpa_auth)) { 458214501Srpaulo wpa_printf(MSG_ERROR, "Could not generate WPA IE."); 459214501Srpaulo os_free(wpa_auth); 460214501Srpaulo return NULL; 461214501Srpaulo } 462214501Srpaulo 463252726Srpaulo wpa_auth->group = wpa_group_init(wpa_auth, 0, 1); 464214501Srpaulo if (wpa_auth->group == NULL) { 465214501Srpaulo os_free(wpa_auth->wpa_ie); 466214501Srpaulo os_free(wpa_auth); 467214501Srpaulo return NULL; 468214501Srpaulo } 469214501Srpaulo 470214501Srpaulo wpa_auth->pmksa = pmksa_cache_auth_init(wpa_auth_pmksa_free_cb, 471214501Srpaulo wpa_auth); 472214501Srpaulo if (wpa_auth->pmksa == NULL) { 473214501Srpaulo wpa_printf(MSG_ERROR, "PMKSA cache initialization failed."); 474281806Srpaulo os_free(wpa_auth->group); 475214501Srpaulo os_free(wpa_auth->wpa_ie); 476214501Srpaulo os_free(wpa_auth); 477214501Srpaulo return NULL; 478214501Srpaulo } 479214501Srpaulo 480346981Scy#ifdef CONFIG_IEEE80211R_AP 481214501Srpaulo wpa_auth->ft_pmk_cache = wpa_ft_pmk_cache_init(); 482214501Srpaulo if (wpa_auth->ft_pmk_cache == NULL) { 483214501Srpaulo wpa_printf(MSG_ERROR, "FT PMK cache initialization failed."); 484281806Srpaulo os_free(wpa_auth->group); 485214501Srpaulo os_free(wpa_auth->wpa_ie); 486214501Srpaulo pmksa_cache_auth_deinit(wpa_auth->pmksa); 487214501Srpaulo os_free(wpa_auth); 488214501Srpaulo return NULL; 489214501Srpaulo } 490346981Scy#endif /* CONFIG_IEEE80211R_AP */ 491214501Srpaulo 492214501Srpaulo if (wpa_auth->conf.wpa_gmk_rekey) { 493214501Srpaulo eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0, 494214501Srpaulo wpa_rekey_gmk, wpa_auth, NULL); 495214501Srpaulo } 496214501Srpaulo 497214501Srpaulo if (wpa_auth->conf.wpa_group_rekey) { 498214501Srpaulo eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, 0, 499214501Srpaulo wpa_rekey_gtk, wpa_auth, NULL); 500214501Srpaulo } 501214501Srpaulo 502281806Srpaulo#ifdef CONFIG_P2P 503281806Srpaulo if (WPA_GET_BE32(conf->ip_addr_start)) { 504281806Srpaulo int count = WPA_GET_BE32(conf->ip_addr_end) - 505281806Srpaulo WPA_GET_BE32(conf->ip_addr_start) + 1; 506281806Srpaulo if (count > 1000) 507281806Srpaulo count = 1000; 508281806Srpaulo if (count > 0) 509281806Srpaulo wpa_auth->ip_pool = bitfield_alloc(count); 510281806Srpaulo } 511281806Srpaulo#endif /* CONFIG_P2P */ 512281806Srpaulo 513214501Srpaulo return wpa_auth; 514214501Srpaulo} 515214501Srpaulo 516214501Srpaulo 517252726Srpauloint wpa_init_keys(struct wpa_authenticator *wpa_auth) 518252726Srpaulo{ 519252726Srpaulo struct wpa_group *group = wpa_auth->group; 520252726Srpaulo 521252726Srpaulo wpa_printf(MSG_DEBUG, "WPA: Start group state machine to set initial " 522252726Srpaulo "keys"); 523252726Srpaulo wpa_group_sm_step(wpa_auth, group); 524252726Srpaulo group->GInit = FALSE; 525252726Srpaulo wpa_group_sm_step(wpa_auth, group); 526281806Srpaulo if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) 527281806Srpaulo return -1; 528252726Srpaulo return 0; 529252726Srpaulo} 530252726Srpaulo 531252726Srpaulo 532214501Srpaulo/** 533214501Srpaulo * wpa_deinit - Deinitialize WPA authenticator 534214501Srpaulo * @wpa_auth: Pointer to WPA authenticator data from wpa_init() 535214501Srpaulo */ 536214501Srpaulovoid wpa_deinit(struct wpa_authenticator *wpa_auth) 537214501Srpaulo{ 538214501Srpaulo struct wpa_group *group, *prev; 539214501Srpaulo 540214501Srpaulo eloop_cancel_timeout(wpa_rekey_gmk, wpa_auth, NULL); 541214501Srpaulo eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL); 542214501Srpaulo 543214501Srpaulo pmksa_cache_auth_deinit(wpa_auth->pmksa); 544214501Srpaulo 545346981Scy#ifdef CONFIG_IEEE80211R_AP 546214501Srpaulo wpa_ft_pmk_cache_deinit(wpa_auth->ft_pmk_cache); 547214501Srpaulo wpa_auth->ft_pmk_cache = NULL; 548346981Scy wpa_ft_deinit(wpa_auth); 549346981Scy#endif /* CONFIG_IEEE80211R_AP */ 550214501Srpaulo 551281806Srpaulo#ifdef CONFIG_P2P 552281806Srpaulo bitfield_free(wpa_auth->ip_pool); 553281806Srpaulo#endif /* CONFIG_P2P */ 554281806Srpaulo 555281806Srpaulo 556214501Srpaulo os_free(wpa_auth->wpa_ie); 557214501Srpaulo 558214501Srpaulo group = wpa_auth->group; 559214501Srpaulo while (group) { 560214501Srpaulo prev = group; 561214501Srpaulo group = group->next; 562214501Srpaulo os_free(prev); 563214501Srpaulo } 564214501Srpaulo 565214501Srpaulo os_free(wpa_auth); 566214501Srpaulo} 567214501Srpaulo 568214501Srpaulo 569214501Srpaulo/** 570214501Srpaulo * wpa_reconfig - Update WPA authenticator configuration 571214501Srpaulo * @wpa_auth: Pointer to WPA authenticator data from wpa_init() 572214501Srpaulo * @conf: Configuration for WPA authenticator 573214501Srpaulo */ 574214501Srpauloint wpa_reconfig(struct wpa_authenticator *wpa_auth, 575214501Srpaulo struct wpa_auth_config *conf) 576214501Srpaulo{ 577214501Srpaulo struct wpa_group *group; 578214501Srpaulo if (wpa_auth == NULL) 579214501Srpaulo return 0; 580214501Srpaulo 581214501Srpaulo os_memcpy(&wpa_auth->conf, conf, sizeof(*conf)); 582214501Srpaulo if (wpa_auth_gen_wpa_ie(wpa_auth)) { 583214501Srpaulo wpa_printf(MSG_ERROR, "Could not generate WPA IE."); 584214501Srpaulo return -1; 585214501Srpaulo } 586214501Srpaulo 587214501Srpaulo /* 588214501Srpaulo * Reinitialize GTK to make sure it is suitable for the new 589214501Srpaulo * configuration. 590214501Srpaulo */ 591214501Srpaulo group = wpa_auth->group; 592252726Srpaulo group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group); 593214501Srpaulo group->GInit = TRUE; 594214501Srpaulo wpa_group_sm_step(wpa_auth, group); 595214501Srpaulo group->GInit = FALSE; 596214501Srpaulo wpa_group_sm_step(wpa_auth, group); 597214501Srpaulo 598214501Srpaulo return 0; 599214501Srpaulo} 600214501Srpaulo 601214501Srpaulo 602214501Srpaulostruct wpa_state_machine * 603281806Srpaulowpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr, 604281806Srpaulo const u8 *p2p_dev_addr) 605214501Srpaulo{ 606214501Srpaulo struct wpa_state_machine *sm; 607214501Srpaulo 608281806Srpaulo if (wpa_auth->group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) 609281806Srpaulo return NULL; 610281806Srpaulo 611214501Srpaulo sm = os_zalloc(sizeof(struct wpa_state_machine)); 612214501Srpaulo if (sm == NULL) 613214501Srpaulo return NULL; 614214501Srpaulo os_memcpy(sm->addr, addr, ETH_ALEN); 615281806Srpaulo if (p2p_dev_addr) 616281806Srpaulo os_memcpy(sm->p2p_dev_addr, p2p_dev_addr, ETH_ALEN); 617214501Srpaulo 618214501Srpaulo sm->wpa_auth = wpa_auth; 619214501Srpaulo sm->group = wpa_auth->group; 620289549Srpaulo wpa_group_get(sm->wpa_auth, sm->group); 621214501Srpaulo 622214501Srpaulo return sm; 623214501Srpaulo} 624214501Srpaulo 625214501Srpaulo 626214501Srpauloint wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, 627214501Srpaulo struct wpa_state_machine *sm) 628214501Srpaulo{ 629214501Srpaulo if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) 630214501Srpaulo return -1; 631214501Srpaulo 632346981Scy#ifdef CONFIG_IEEE80211R_AP 633214501Srpaulo if (sm->ft_completed) { 634214501Srpaulo wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, 635214501Srpaulo "FT authentication already completed - do not " 636214501Srpaulo "start 4-way handshake"); 637281806Srpaulo /* Go to PTKINITDONE state to allow GTK rekeying */ 638281806Srpaulo sm->wpa_ptk_state = WPA_PTK_PTKINITDONE; 639346981Scy sm->Pair = TRUE; 640214501Srpaulo return 0; 641214501Srpaulo } 642346981Scy#endif /* CONFIG_IEEE80211R_AP */ 643214501Srpaulo 644346981Scy#ifdef CONFIG_FILS 645346981Scy if (sm->fils_completed) { 646346981Scy wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, 647346981Scy "FILS authentication already completed - do not start 4-way handshake"); 648346981Scy /* Go to PTKINITDONE state to allow GTK rekeying */ 649346981Scy sm->wpa_ptk_state = WPA_PTK_PTKINITDONE; 650346981Scy sm->Pair = TRUE; 651346981Scy return 0; 652346981Scy } 653346981Scy#endif /* CONFIG_FILS */ 654346981Scy 655214501Srpaulo if (sm->started) { 656214501Srpaulo os_memset(&sm->key_replay, 0, sizeof(sm->key_replay)); 657214501Srpaulo sm->ReAuthenticationRequest = TRUE; 658214501Srpaulo return wpa_sm_step(sm); 659214501Srpaulo } 660214501Srpaulo 661214501Srpaulo wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, 662214501Srpaulo "start authentication"); 663214501Srpaulo sm->started = 1; 664214501Srpaulo 665214501Srpaulo sm->Init = TRUE; 666214501Srpaulo if (wpa_sm_step(sm) == 1) 667214501Srpaulo return 1; /* should not really happen */ 668214501Srpaulo sm->Init = FALSE; 669214501Srpaulo sm->AuthenticationRequest = TRUE; 670214501Srpaulo return wpa_sm_step(sm); 671214501Srpaulo} 672214501Srpaulo 673214501Srpaulo 674214501Srpaulovoid wpa_auth_sta_no_wpa(struct wpa_state_machine *sm) 675214501Srpaulo{ 676214501Srpaulo /* WPA/RSN was not used - clear WPA state. This is needed if the STA 677214501Srpaulo * reassociates back to the same AP while the previous entry for the 678214501Srpaulo * STA has not yet been removed. */ 679214501Srpaulo if (sm == NULL) 680214501Srpaulo return; 681214501Srpaulo 682214501Srpaulo sm->wpa_key_mgmt = 0; 683214501Srpaulo} 684214501Srpaulo 685214501Srpaulo 686214501Srpaulostatic void wpa_free_sta_sm(struct wpa_state_machine *sm) 687214501Srpaulo{ 688281806Srpaulo#ifdef CONFIG_P2P 689281806Srpaulo if (WPA_GET_BE32(sm->ip_addr)) { 690281806Srpaulo u32 start; 691281806Srpaulo wpa_printf(MSG_DEBUG, "P2P: Free assigned IP " 692281806Srpaulo "address %u.%u.%u.%u from " MACSTR, 693281806Srpaulo sm->ip_addr[0], sm->ip_addr[1], 694281806Srpaulo sm->ip_addr[2], sm->ip_addr[3], 695281806Srpaulo MAC2STR(sm->addr)); 696281806Srpaulo start = WPA_GET_BE32(sm->wpa_auth->conf.ip_addr_start); 697281806Srpaulo bitfield_clear(sm->wpa_auth->ip_pool, 698281806Srpaulo WPA_GET_BE32(sm->ip_addr) - start); 699281806Srpaulo } 700281806Srpaulo#endif /* CONFIG_P2P */ 701252726Srpaulo if (sm->GUpdateStationKeys) { 702252726Srpaulo sm->group->GKeyDoneStations--; 703252726Srpaulo sm->GUpdateStationKeys = FALSE; 704252726Srpaulo } 705346981Scy#ifdef CONFIG_IEEE80211R_AP 706214501Srpaulo os_free(sm->assoc_resp_ftie); 707281806Srpaulo wpabuf_free(sm->ft_pending_req_ies); 708346981Scy#endif /* CONFIG_IEEE80211R_AP */ 709214501Srpaulo os_free(sm->last_rx_eapol_key); 710214501Srpaulo os_free(sm->wpa_ie); 711289549Srpaulo wpa_group_put(sm->wpa_auth, sm->group); 712346981Scy#ifdef CONFIG_DPP2 713346981Scy wpabuf_clear_free(sm->dpp_z); 714346981Scy#endif /* CONFIG_DPP2 */ 715346981Scy bin_clear_free(sm, sizeof(*sm)); 716214501Srpaulo} 717214501Srpaulo 718214501Srpaulo 719214501Srpaulovoid wpa_auth_sta_deinit(struct wpa_state_machine *sm) 720214501Srpaulo{ 721214501Srpaulo if (sm == NULL) 722214501Srpaulo return; 723214501Srpaulo 724214501Srpaulo if (sm->wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) { 725214501Srpaulo wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 726214501Srpaulo "strict rekeying - force GTK rekey since STA " 727214501Srpaulo "is leaving"); 728346981Scy if (eloop_deplete_timeout(0, 500000, wpa_rekey_gtk, 729346981Scy sm->wpa_auth, NULL) == -1) 730346981Scy eloop_register_timeout(0, 500000, wpa_rekey_gtk, sm->wpa_auth, 731346981Scy NULL); 732214501Srpaulo } 733214501Srpaulo 734214501Srpaulo eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm); 735252726Srpaulo sm->pending_1_of_4_timeout = 0; 736214501Srpaulo eloop_cancel_timeout(wpa_sm_call_step, sm, NULL); 737214501Srpaulo eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); 738346981Scy#ifdef CONFIG_IEEE80211R_AP 739346981Scy wpa_ft_sta_deinit(sm); 740346981Scy#endif /* CONFIG_IEEE80211R_AP */ 741214501Srpaulo if (sm->in_step_loop) { 742214501Srpaulo /* Must not free state machine while wpa_sm_step() is running. 743214501Srpaulo * Freeing will be completed in the end of wpa_sm_step(). */ 744214501Srpaulo wpa_printf(MSG_DEBUG, "WPA: Registering pending STA state " 745214501Srpaulo "machine deinit for " MACSTR, MAC2STR(sm->addr)); 746214501Srpaulo sm->pending_deinit = 1; 747214501Srpaulo } else 748214501Srpaulo wpa_free_sta_sm(sm); 749214501Srpaulo} 750214501Srpaulo 751214501Srpaulo 752214501Srpaulostatic void wpa_request_new_ptk(struct wpa_state_machine *sm) 753214501Srpaulo{ 754214501Srpaulo if (sm == NULL) 755214501Srpaulo return; 756214501Srpaulo 757214501Srpaulo sm->PTKRequest = TRUE; 758214501Srpaulo sm->PTK_valid = 0; 759214501Srpaulo} 760214501Srpaulo 761214501Srpaulo 762252726Srpaulostatic int wpa_replay_counter_valid(struct wpa_key_replay_counter *ctr, 763214501Srpaulo const u8 *replay_counter) 764214501Srpaulo{ 765214501Srpaulo int i; 766214501Srpaulo for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { 767252726Srpaulo if (!ctr[i].valid) 768214501Srpaulo break; 769252726Srpaulo if (os_memcmp(replay_counter, ctr[i].counter, 770214501Srpaulo WPA_REPLAY_COUNTER_LEN) == 0) 771214501Srpaulo return 1; 772214501Srpaulo } 773214501Srpaulo return 0; 774214501Srpaulo} 775214501Srpaulo 776214501Srpaulo 777252726Srpaulostatic void wpa_replay_counter_mark_invalid(struct wpa_key_replay_counter *ctr, 778252726Srpaulo const u8 *replay_counter) 779252726Srpaulo{ 780252726Srpaulo int i; 781252726Srpaulo for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { 782252726Srpaulo if (ctr[i].valid && 783252726Srpaulo (replay_counter == NULL || 784252726Srpaulo os_memcmp(replay_counter, ctr[i].counter, 785252726Srpaulo WPA_REPLAY_COUNTER_LEN) == 0)) 786252726Srpaulo ctr[i].valid = FALSE; 787252726Srpaulo } 788252726Srpaulo} 789252726Srpaulo 790252726Srpaulo 791346981Scy#ifdef CONFIG_IEEE80211R_AP 792214501Srpaulostatic int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth, 793214501Srpaulo struct wpa_state_machine *sm, 794214501Srpaulo struct wpa_eapol_ie_parse *kde) 795214501Srpaulo{ 796214501Srpaulo struct wpa_ie_data ie; 797214501Srpaulo struct rsn_mdie *mdie; 798214501Srpaulo 799214501Srpaulo if (wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0 || 800214501Srpaulo ie.num_pmkid != 1 || ie.pmkid == NULL) { 801214501Srpaulo wpa_printf(MSG_DEBUG, "FT: No PMKR1Name in " 802214501Srpaulo "FT 4-way handshake message 2/4"); 803214501Srpaulo return -1; 804214501Srpaulo } 805214501Srpaulo 806214501Srpaulo os_memcpy(sm->sup_pmk_r1_name, ie.pmkid, PMKID_LEN); 807214501Srpaulo wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Supplicant", 808214501Srpaulo sm->sup_pmk_r1_name, PMKID_LEN); 809214501Srpaulo 810214501Srpaulo if (!kde->mdie || !kde->ftie) { 811214501Srpaulo wpa_printf(MSG_DEBUG, "FT: No %s in FT 4-way handshake " 812214501Srpaulo "message 2/4", kde->mdie ? "FTIE" : "MDIE"); 813214501Srpaulo return -1; 814214501Srpaulo } 815214501Srpaulo 816214501Srpaulo mdie = (struct rsn_mdie *) (kde->mdie + 2); 817214501Srpaulo if (kde->mdie[1] < sizeof(struct rsn_mdie) || 818214501Srpaulo os_memcmp(wpa_auth->conf.mobility_domain, mdie->mobility_domain, 819214501Srpaulo MOBILITY_DOMAIN_ID_LEN) != 0) { 820214501Srpaulo wpa_printf(MSG_DEBUG, "FT: MDIE mismatch"); 821214501Srpaulo return -1; 822214501Srpaulo } 823214501Srpaulo 824214501Srpaulo if (sm->assoc_resp_ftie && 825214501Srpaulo (kde->ftie[1] != sm->assoc_resp_ftie[1] || 826214501Srpaulo os_memcmp(kde->ftie, sm->assoc_resp_ftie, 827214501Srpaulo 2 + sm->assoc_resp_ftie[1]) != 0)) { 828214501Srpaulo wpa_printf(MSG_DEBUG, "FT: FTIE mismatch"); 829214501Srpaulo wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 2/4", 830214501Srpaulo kde->ftie, kde->ftie_len); 831214501Srpaulo wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)AssocResp", 832214501Srpaulo sm->assoc_resp_ftie, 2 + sm->assoc_resp_ftie[1]); 833214501Srpaulo return -1; 834214501Srpaulo } 835214501Srpaulo 836214501Srpaulo return 0; 837214501Srpaulo} 838346981Scy#endif /* CONFIG_IEEE80211R_AP */ 839214501Srpaulo 840214501Srpaulo 841252726Srpaulostatic int wpa_receive_error_report(struct wpa_authenticator *wpa_auth, 842252726Srpaulo struct wpa_state_machine *sm, int group) 843252726Srpaulo{ 844252726Srpaulo /* Supplicant reported a Michael MIC error */ 845252726Srpaulo wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, 846252726Srpaulo "received EAPOL-Key Error Request " 847252726Srpaulo "(STA detected Michael MIC failure (group=%d))", 848252726Srpaulo group); 849252726Srpaulo 850252726Srpaulo if (group && wpa_auth->conf.wpa_group != WPA_CIPHER_TKIP) { 851252726Srpaulo wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 852252726Srpaulo "ignore Michael MIC failure report since " 853252726Srpaulo "group cipher is not TKIP"); 854252726Srpaulo } else if (!group && sm->pairwise != WPA_CIPHER_TKIP) { 855252726Srpaulo wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 856252726Srpaulo "ignore Michael MIC failure report since " 857252726Srpaulo "pairwise cipher is not TKIP"); 858252726Srpaulo } else { 859252726Srpaulo if (wpa_auth_mic_failure_report(wpa_auth, sm->addr) > 0) 860252726Srpaulo return 1; /* STA entry was removed */ 861252726Srpaulo sm->dot11RSNAStatsTKIPRemoteMICFailures++; 862252726Srpaulo wpa_auth->dot11RSNAStatsTKIPRemoteMICFailures++; 863252726Srpaulo } 864252726Srpaulo 865252726Srpaulo /* 866252726Srpaulo * Error report is not a request for a new key handshake, but since 867252726Srpaulo * Authenticator may do it, let's change the keys now anyway. 868252726Srpaulo */ 869252726Srpaulo wpa_request_new_ptk(sm); 870252726Srpaulo return 0; 871252726Srpaulo} 872252726Srpaulo 873252726Srpaulo 874281806Srpaulostatic int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data, 875281806Srpaulo size_t data_len) 876281806Srpaulo{ 877281806Srpaulo struct wpa_ptk PTK; 878281806Srpaulo int ok = 0; 879281806Srpaulo const u8 *pmk = NULL; 880346981Scy size_t pmk_len; 881346981Scy int vlan_id = 0; 882281806Srpaulo 883346981Scy os_memset(&PTK, 0, sizeof(PTK)); 884281806Srpaulo for (;;) { 885346981Scy if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) && 886346981Scy !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) { 887281806Srpaulo pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, 888346981Scy sm->p2p_dev_addr, pmk, &pmk_len, 889346981Scy &vlan_id); 890281806Srpaulo if (pmk == NULL) 891281806Srpaulo break; 892346981Scy#ifdef CONFIG_IEEE80211R_AP 893346981Scy if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) { 894346981Scy os_memcpy(sm->xxkey, pmk, pmk_len); 895346981Scy sm->xxkey_len = pmk_len; 896346981Scy } 897346981Scy#endif /* CONFIG_IEEE80211R_AP */ 898337817Scy } else { 899281806Srpaulo pmk = sm->PMK; 900337817Scy pmk_len = sm->pmk_len; 901337817Scy } 902281806Srpaulo 903346981Scy if (wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK) < 0) 904346981Scy break; 905281806Srpaulo 906346981Scy if (wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK, 907346981Scy data, data_len) == 0) { 908346981Scy if (sm->PMK != pmk) { 909346981Scy os_memcpy(sm->PMK, pmk, pmk_len); 910346981Scy sm->pmk_len = pmk_len; 911346981Scy } 912281806Srpaulo ok = 1; 913281806Srpaulo break; 914281806Srpaulo } 915281806Srpaulo 916346981Scy if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) || 917346981Scy wpa_key_mgmt_sae(sm->wpa_key_mgmt)) 918281806Srpaulo break; 919281806Srpaulo } 920281806Srpaulo 921281806Srpaulo if (!ok) { 922281806Srpaulo wpa_printf(MSG_DEBUG, 923281806Srpaulo "WPA: Earlier SNonce did not result in matching MIC"); 924281806Srpaulo return -1; 925281806Srpaulo } 926281806Srpaulo 927281806Srpaulo wpa_printf(MSG_DEBUG, 928281806Srpaulo "WPA: Earlier SNonce resulted in matching MIC"); 929281806Srpaulo sm->alt_snonce_valid = 0; 930346981Scy 931346981Scy if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) && 932346981Scy wpa_auth_update_vlan(sm->wpa_auth, sm->addr, vlan_id) < 0) 933346981Scy return -1; 934346981Scy 935281806Srpaulo os_memcpy(sm->SNonce, sm->alt_SNonce, WPA_NONCE_LEN); 936281806Srpaulo os_memcpy(&sm->PTK, &PTK, sizeof(PTK)); 937351611Scy forced_memzero(&PTK, sizeof(PTK)); 938281806Srpaulo sm->PTK_valid = TRUE; 939281806Srpaulo 940281806Srpaulo return 0; 941281806Srpaulo} 942281806Srpaulo 943281806Srpaulo 944214501Srpaulovoid wpa_receive(struct wpa_authenticator *wpa_auth, 945214501Srpaulo struct wpa_state_machine *sm, 946214501Srpaulo u8 *data, size_t data_len) 947214501Srpaulo{ 948214501Srpaulo struct ieee802_1x_hdr *hdr; 949214501Srpaulo struct wpa_eapol_key *key; 950214501Srpaulo u16 key_info, key_data_length; 951346981Scy enum { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST } msg; 952214501Srpaulo char *msgtxt; 953214501Srpaulo struct wpa_eapol_ie_parse kde; 954346981Scy const u8 *key_data; 955346981Scy size_t keyhdrlen, mic_len; 956346981Scy u8 *mic; 957214501Srpaulo 958214501Srpaulo if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) 959214501Srpaulo return; 960346981Scy wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL data", data, data_len); 961214501Srpaulo 962346981Scy mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len); 963346981Scy keyhdrlen = sizeof(*key) + mic_len + 2; 964281806Srpaulo 965346981Scy if (data_len < sizeof(*hdr) + keyhdrlen) { 966346981Scy wpa_printf(MSG_DEBUG, "WPA: Ignore too short EAPOL-Key frame"); 967214501Srpaulo return; 968346981Scy } 969214501Srpaulo 970214501Srpaulo hdr = (struct ieee802_1x_hdr *) data; 971214501Srpaulo key = (struct wpa_eapol_key *) (hdr + 1); 972346981Scy mic = (u8 *) (key + 1); 973214501Srpaulo key_info = WPA_GET_BE16(key->key_info); 974346981Scy key_data = mic + mic_len + 2; 975346981Scy key_data_length = WPA_GET_BE16(mic + mic_len); 976252726Srpaulo wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR 977346981Scy " key_info=0x%x type=%u mic_len=%u key_data_length=%u", 978346981Scy MAC2STR(sm->addr), key_info, key->type, 979346981Scy (unsigned int) mic_len, key_data_length); 980346981Scy wpa_hexdump(MSG_MSGDUMP, 981346981Scy "WPA: EAPOL-Key header (ending before Key MIC)", 982346981Scy key, sizeof(*key)); 983346981Scy wpa_hexdump(MSG_MSGDUMP, "WPA: EAPOL-Key Key MIC", 984346981Scy mic, mic_len); 985281806Srpaulo if (key_data_length > data_len - sizeof(*hdr) - keyhdrlen) { 986214501Srpaulo wpa_printf(MSG_INFO, "WPA: Invalid EAPOL-Key frame - " 987214501Srpaulo "key_data overflow (%d > %lu)", 988214501Srpaulo key_data_length, 989214501Srpaulo (unsigned long) (data_len - sizeof(*hdr) - 990281806Srpaulo keyhdrlen)); 991214501Srpaulo return; 992214501Srpaulo } 993214501Srpaulo 994214501Srpaulo if (sm->wpa == WPA_VERSION_WPA2) { 995252726Srpaulo if (key->type == EAPOL_KEY_TYPE_WPA) { 996252726Srpaulo /* 997252726Srpaulo * Some deployed station implementations seem to send 998252726Srpaulo * msg 4/4 with incorrect type value in WPA2 mode. 999252726Srpaulo */ 1000252726Srpaulo wpa_printf(MSG_DEBUG, "Workaround: Allow EAPOL-Key " 1001252726Srpaulo "with unexpected WPA type in RSN mode"); 1002252726Srpaulo } else if (key->type != EAPOL_KEY_TYPE_RSN) { 1003214501Srpaulo wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with " 1004214501Srpaulo "unexpected type %d in RSN mode", 1005214501Srpaulo key->type); 1006214501Srpaulo return; 1007214501Srpaulo } 1008214501Srpaulo } else { 1009214501Srpaulo if (key->type != EAPOL_KEY_TYPE_WPA) { 1010214501Srpaulo wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with " 1011214501Srpaulo "unexpected type %d in WPA mode", 1012214501Srpaulo key->type); 1013214501Srpaulo return; 1014214501Srpaulo } 1015214501Srpaulo } 1016214501Srpaulo 1017252726Srpaulo wpa_hexdump(MSG_DEBUG, "WPA: Received Key Nonce", key->key_nonce, 1018252726Srpaulo WPA_NONCE_LEN); 1019252726Srpaulo wpa_hexdump(MSG_DEBUG, "WPA: Received Replay Counter", 1020252726Srpaulo key->replay_counter, WPA_REPLAY_COUNTER_LEN); 1021252726Srpaulo 1022214501Srpaulo /* FIX: verify that the EAPOL-Key frame was encrypted if pairwise keys 1023214501Srpaulo * are set */ 1024214501Srpaulo 1025346981Scy if (key_info & WPA_KEY_INFO_SMK_MESSAGE) { 1026346981Scy wpa_printf(MSG_DEBUG, "WPA: Ignore SMK message"); 1027346981Scy return; 1028346981Scy } 1029346981Scy 1030346981Scy if (key_info & WPA_KEY_INFO_REQUEST) { 1031214501Srpaulo msg = REQUEST; 1032214501Srpaulo msgtxt = "Request"; 1033214501Srpaulo } else if (!(key_info & WPA_KEY_INFO_KEY_TYPE)) { 1034214501Srpaulo msg = GROUP_2; 1035214501Srpaulo msgtxt = "2/2 Group"; 1036346981Scy } else if (key_data_length == 0 || 1037346981Scy (mic_len == 0 && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) && 1038346981Scy key_data_length == AES_BLOCK_SIZE)) { 1039214501Srpaulo msg = PAIRWISE_4; 1040214501Srpaulo msgtxt = "4/4 Pairwise"; 1041214501Srpaulo } else { 1042214501Srpaulo msg = PAIRWISE_2; 1043214501Srpaulo msgtxt = "2/4 Pairwise"; 1044214501Srpaulo } 1045214501Srpaulo 1046214501Srpaulo if (msg == REQUEST || msg == PAIRWISE_2 || msg == PAIRWISE_4 || 1047214501Srpaulo msg == GROUP_2) { 1048214501Srpaulo u16 ver = key_info & WPA_KEY_INFO_TYPE_MASK; 1049252726Srpaulo if (sm->pairwise == WPA_CIPHER_CCMP || 1050252726Srpaulo sm->pairwise == WPA_CIPHER_GCMP) { 1051346981Scy if (wpa_use_cmac(sm->wpa_key_mgmt) && 1052346981Scy !wpa_use_akm_defined(sm->wpa_key_mgmt) && 1053214501Srpaulo ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { 1054214501Srpaulo wpa_auth_logger(wpa_auth, sm->addr, 1055214501Srpaulo LOGGER_WARNING, 1056214501Srpaulo "advertised support for " 1057214501Srpaulo "AES-128-CMAC, but did not " 1058214501Srpaulo "use it"); 1059214501Srpaulo return; 1060214501Srpaulo } 1061214501Srpaulo 1062346981Scy if (!wpa_use_cmac(sm->wpa_key_mgmt) && 1063346981Scy !wpa_use_akm_defined(sm->wpa_key_mgmt) && 1064214501Srpaulo ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { 1065214501Srpaulo wpa_auth_logger(wpa_auth, sm->addr, 1066214501Srpaulo LOGGER_WARNING, 1067214501Srpaulo "did not use HMAC-SHA1-AES " 1068252726Srpaulo "with CCMP/GCMP"); 1069214501Srpaulo return; 1070214501Srpaulo } 1071214501Srpaulo } 1072281806Srpaulo 1073346981Scy if (wpa_use_akm_defined(sm->wpa_key_mgmt) && 1074281806Srpaulo ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) { 1075281806Srpaulo wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING, 1076281806Srpaulo "did not use EAPOL-Key descriptor version 0 as required for AKM-defined cases"); 1077281806Srpaulo return; 1078281806Srpaulo } 1079214501Srpaulo } 1080214501Srpaulo 1081214501Srpaulo if (key_info & WPA_KEY_INFO_REQUEST) { 1082214501Srpaulo if (sm->req_replay_counter_used && 1083214501Srpaulo os_memcmp(key->replay_counter, sm->req_replay_counter, 1084214501Srpaulo WPA_REPLAY_COUNTER_LEN) <= 0) { 1085214501Srpaulo wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING, 1086214501Srpaulo "received EAPOL-Key request with " 1087214501Srpaulo "replayed counter"); 1088214501Srpaulo return; 1089214501Srpaulo } 1090214501Srpaulo } 1091214501Srpaulo 1092214501Srpaulo if (!(key_info & WPA_KEY_INFO_REQUEST) && 1093252726Srpaulo !wpa_replay_counter_valid(sm->key_replay, key->replay_counter)) { 1094214501Srpaulo int i; 1095252726Srpaulo 1096252726Srpaulo if (msg == PAIRWISE_2 && 1097252726Srpaulo wpa_replay_counter_valid(sm->prev_key_replay, 1098252726Srpaulo key->replay_counter) && 1099252726Srpaulo sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING && 1100252726Srpaulo os_memcmp(sm->SNonce, key->key_nonce, WPA_NONCE_LEN) != 0) 1101252726Srpaulo { 1102252726Srpaulo /* 1103252726Srpaulo * Some supplicant implementations (e.g., Windows XP 1104252726Srpaulo * WZC) update SNonce for each EAPOL-Key 2/4. This 1105252726Srpaulo * breaks the workaround on accepting any of the 1106252726Srpaulo * pending requests, so allow the SNonce to be updated 1107252726Srpaulo * even if we have already sent out EAPOL-Key 3/4. 1108252726Srpaulo */ 1109252726Srpaulo wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, 1110252726Srpaulo "Process SNonce update from STA " 1111252726Srpaulo "based on retransmitted EAPOL-Key " 1112252726Srpaulo "1/4"); 1113252726Srpaulo sm->update_snonce = 1; 1114281806Srpaulo os_memcpy(sm->alt_SNonce, sm->SNonce, WPA_NONCE_LEN); 1115281806Srpaulo sm->alt_snonce_valid = TRUE; 1116281806Srpaulo os_memcpy(sm->alt_replay_counter, 1117281806Srpaulo sm->key_replay[0].counter, 1118281806Srpaulo WPA_REPLAY_COUNTER_LEN); 1119252726Srpaulo goto continue_processing; 1120252726Srpaulo } 1121252726Srpaulo 1122281806Srpaulo if (msg == PAIRWISE_4 && sm->alt_snonce_valid && 1123281806Srpaulo sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING && 1124281806Srpaulo os_memcmp(key->replay_counter, sm->alt_replay_counter, 1125281806Srpaulo WPA_REPLAY_COUNTER_LEN) == 0) { 1126281806Srpaulo /* 1127281806Srpaulo * Supplicant may still be using the old SNonce since 1128281806Srpaulo * there was two EAPOL-Key 2/4 messages and they had 1129281806Srpaulo * different SNonce values. 1130281806Srpaulo */ 1131281806Srpaulo wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, 1132281806Srpaulo "Try to process received EAPOL-Key 4/4 based on old Replay Counter and SNonce from an earlier EAPOL-Key 1/4"); 1133281806Srpaulo goto continue_processing; 1134281806Srpaulo } 1135281806Srpaulo 1136252726Srpaulo if (msg == PAIRWISE_2 && 1137252726Srpaulo wpa_replay_counter_valid(sm->prev_key_replay, 1138252726Srpaulo key->replay_counter) && 1139252726Srpaulo sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING) { 1140252726Srpaulo wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, 1141252726Srpaulo "ignore retransmitted EAPOL-Key %s - " 1142252726Srpaulo "SNonce did not change", msgtxt); 1143252726Srpaulo } else { 1144252726Srpaulo wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, 1145252726Srpaulo "received EAPOL-Key %s with " 1146252726Srpaulo "unexpected replay counter", msgtxt); 1147252726Srpaulo } 1148214501Srpaulo for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { 1149214501Srpaulo if (!sm->key_replay[i].valid) 1150214501Srpaulo break; 1151214501Srpaulo wpa_hexdump(MSG_DEBUG, "pending replay counter", 1152214501Srpaulo sm->key_replay[i].counter, 1153214501Srpaulo WPA_REPLAY_COUNTER_LEN); 1154214501Srpaulo } 1155214501Srpaulo wpa_hexdump(MSG_DEBUG, "received replay counter", 1156214501Srpaulo key->replay_counter, WPA_REPLAY_COUNTER_LEN); 1157214501Srpaulo return; 1158214501Srpaulo } 1159214501Srpaulo 1160252726Srpaulocontinue_processing: 1161346981Scy#ifdef CONFIG_FILS 1162346981Scy if (sm->wpa == WPA_VERSION_WPA2 && mic_len == 0 && 1163346981Scy !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { 1164346981Scy wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, 1165346981Scy "WPA: Encr Key Data bit not set even though AEAD cipher is supposed to be used - drop frame"); 1166346981Scy return; 1167346981Scy } 1168346981Scy#endif /* CONFIG_FILS */ 1169346981Scy 1170214501Srpaulo switch (msg) { 1171214501Srpaulo case PAIRWISE_2: 1172214501Srpaulo if (sm->wpa_ptk_state != WPA_PTK_PTKSTART && 1173252726Srpaulo sm->wpa_ptk_state != WPA_PTK_PTKCALCNEGOTIATING && 1174252726Srpaulo (!sm->update_snonce || 1175252726Srpaulo sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING)) { 1176214501Srpaulo wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, 1177214501Srpaulo "received EAPOL-Key msg 2/4 in " 1178214501Srpaulo "invalid state (%d) - dropped", 1179214501Srpaulo sm->wpa_ptk_state); 1180214501Srpaulo return; 1181214501Srpaulo } 1182252726Srpaulo random_add_randomness(key->key_nonce, WPA_NONCE_LEN); 1183252726Srpaulo if (sm->group->reject_4way_hs_for_entropy) { 1184252726Srpaulo /* 1185252726Srpaulo * The system did not have enough entropy to generate 1186252726Srpaulo * strong random numbers. Reject the first 4-way 1187252726Srpaulo * handshake(s) and collect some entropy based on the 1188252726Srpaulo * information from it. Once enough entropy is 1189252726Srpaulo * available, the next atempt will trigger GMK/Key 1190252726Srpaulo * Counter update and the station will be allowed to 1191252726Srpaulo * continue. 1192252726Srpaulo */ 1193252726Srpaulo wpa_printf(MSG_DEBUG, "WPA: Reject 4-way handshake to " 1194252726Srpaulo "collect more entropy for random number " 1195252726Srpaulo "generation"); 1196252726Srpaulo random_mark_pool_ready(); 1197346981Scy wpa_sta_disconnect(wpa_auth, sm->addr, 1198346981Scy WLAN_REASON_PREV_AUTH_NOT_VALID); 1199252726Srpaulo return; 1200252726Srpaulo } 1201214501Srpaulo break; 1202214501Srpaulo case PAIRWISE_4: 1203214501Srpaulo if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING || 1204214501Srpaulo !sm->PTK_valid) { 1205214501Srpaulo wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, 1206214501Srpaulo "received EAPOL-Key msg 4/4 in " 1207214501Srpaulo "invalid state (%d) - dropped", 1208214501Srpaulo sm->wpa_ptk_state); 1209214501Srpaulo return; 1210214501Srpaulo } 1211214501Srpaulo break; 1212214501Srpaulo case GROUP_2: 1213214501Srpaulo if (sm->wpa_ptk_group_state != WPA_PTK_GROUP_REKEYNEGOTIATING 1214214501Srpaulo || !sm->PTK_valid) { 1215214501Srpaulo wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, 1216214501Srpaulo "received EAPOL-Key msg 2/2 in " 1217214501Srpaulo "invalid state (%d) - dropped", 1218214501Srpaulo sm->wpa_ptk_group_state); 1219214501Srpaulo return; 1220214501Srpaulo } 1221214501Srpaulo break; 1222214501Srpaulo case REQUEST: 1223214501Srpaulo break; 1224214501Srpaulo } 1225214501Srpaulo 1226214501Srpaulo wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, 1227214501Srpaulo "received EAPOL-Key frame (%s)", msgtxt); 1228214501Srpaulo 1229214501Srpaulo if (key_info & WPA_KEY_INFO_ACK) { 1230214501Srpaulo wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 1231214501Srpaulo "received invalid EAPOL-Key: Key Ack set"); 1232214501Srpaulo return; 1233214501Srpaulo } 1234214501Srpaulo 1235346981Scy if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt) && 1236346981Scy !(key_info & WPA_KEY_INFO_MIC)) { 1237214501Srpaulo wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 1238214501Srpaulo "received invalid EAPOL-Key: Key MIC not set"); 1239214501Srpaulo return; 1240214501Srpaulo } 1241214501Srpaulo 1242346981Scy#ifdef CONFIG_FILS 1243346981Scy if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) && 1244346981Scy (key_info & WPA_KEY_INFO_MIC)) { 1245346981Scy wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 1246346981Scy "received invalid EAPOL-Key: Key MIC set"); 1247346981Scy return; 1248346981Scy } 1249346981Scy#endif /* CONFIG_FILS */ 1250346981Scy 1251214501Srpaulo sm->MICVerified = FALSE; 1252252726Srpaulo if (sm->PTK_valid && !sm->update_snonce) { 1253346981Scy if (mic_len && 1254346981Scy wpa_verify_key_mic(sm->wpa_key_mgmt, sm->pmk_len, &sm->PTK, 1255346981Scy data, data_len) && 1256281806Srpaulo (msg != PAIRWISE_4 || !sm->alt_snonce_valid || 1257281806Srpaulo wpa_try_alt_snonce(sm, data, data_len))) { 1258214501Srpaulo wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 1259214501Srpaulo "received EAPOL-Key with invalid MIC"); 1260346981Scy#ifdef TEST_FUZZ 1261346981Scy wpa_printf(MSG_INFO, 1262346981Scy "TEST: Ignore Key MIC failure for fuzz testing"); 1263346981Scy goto continue_fuzz; 1264346981Scy#endif /* TEST_FUZZ */ 1265214501Srpaulo return; 1266214501Srpaulo } 1267346981Scy#ifdef CONFIG_FILS 1268346981Scy if (!mic_len && 1269346981Scy wpa_aead_decrypt(sm, &sm->PTK, data, data_len, 1270346981Scy &key_data_length) < 0) { 1271346981Scy wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 1272346981Scy "received EAPOL-Key with invalid MIC"); 1273346981Scy#ifdef TEST_FUZZ 1274346981Scy wpa_printf(MSG_INFO, 1275346981Scy "TEST: Ignore Key MIC failure for fuzz testing"); 1276346981Scy goto continue_fuzz; 1277346981Scy#endif /* TEST_FUZZ */ 1278346981Scy return; 1279346981Scy } 1280346981Scy#endif /* CONFIG_FILS */ 1281346981Scy#ifdef TEST_FUZZ 1282346981Scy continue_fuzz: 1283346981Scy#endif /* TEST_FUZZ */ 1284214501Srpaulo sm->MICVerified = TRUE; 1285214501Srpaulo eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm); 1286252726Srpaulo sm->pending_1_of_4_timeout = 0; 1287214501Srpaulo } 1288214501Srpaulo 1289214501Srpaulo if (key_info & WPA_KEY_INFO_REQUEST) { 1290214501Srpaulo if (sm->MICVerified) { 1291214501Srpaulo sm->req_replay_counter_used = 1; 1292214501Srpaulo os_memcpy(sm->req_replay_counter, key->replay_counter, 1293214501Srpaulo WPA_REPLAY_COUNTER_LEN); 1294214501Srpaulo } else { 1295214501Srpaulo wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 1296214501Srpaulo "received EAPOL-Key request with " 1297214501Srpaulo "invalid MIC"); 1298214501Srpaulo return; 1299214501Srpaulo } 1300214501Srpaulo 1301214501Srpaulo /* 1302214501Srpaulo * TODO: should decrypt key data field if encryption was used; 1303214501Srpaulo * even though MAC address KDE is not normally encrypted, 1304214501Srpaulo * supplicant is allowed to encrypt it. 1305214501Srpaulo */ 1306346981Scy if (key_info & WPA_KEY_INFO_ERROR) { 1307252726Srpaulo if (wpa_receive_error_report( 1308252726Srpaulo wpa_auth, sm, 1309252726Srpaulo !(key_info & WPA_KEY_INFO_KEY_TYPE)) > 0) 1310252726Srpaulo return; /* STA entry was removed */ 1311214501Srpaulo } else if (key_info & WPA_KEY_INFO_KEY_TYPE) { 1312214501Srpaulo wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 1313214501Srpaulo "received EAPOL-Key Request for new " 1314214501Srpaulo "4-Way Handshake"); 1315214501Srpaulo wpa_request_new_ptk(sm); 1316214501Srpaulo } else if (key_data_length > 0 && 1317281806Srpaulo wpa_parse_kde_ies(key_data, key_data_length, 1318281806Srpaulo &kde) == 0 && 1319214501Srpaulo kde.mac_addr) { 1320214501Srpaulo } else { 1321214501Srpaulo wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 1322214501Srpaulo "received EAPOL-Key Request for GTK " 1323214501Srpaulo "rekeying"); 1324214501Srpaulo eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL); 1325214501Srpaulo wpa_rekey_gtk(wpa_auth, NULL); 1326214501Srpaulo } 1327214501Srpaulo } else { 1328252726Srpaulo /* Do not allow the same key replay counter to be reused. */ 1329252726Srpaulo wpa_replay_counter_mark_invalid(sm->key_replay, 1330252726Srpaulo key->replay_counter); 1331252726Srpaulo 1332252726Srpaulo if (msg == PAIRWISE_2) { 1333252726Srpaulo /* 1334252726Srpaulo * Maintain a copy of the pending EAPOL-Key frames in 1335252726Srpaulo * case the EAPOL-Key frame was retransmitted. This is 1336252726Srpaulo * needed to allow EAPOL-Key msg 2/4 reply to another 1337252726Srpaulo * pending msg 1/4 to update the SNonce to work around 1338252726Srpaulo * unexpected supplicant behavior. 1339252726Srpaulo */ 1340252726Srpaulo os_memcpy(sm->prev_key_replay, sm->key_replay, 1341252726Srpaulo sizeof(sm->key_replay)); 1342252726Srpaulo } else { 1343252726Srpaulo os_memset(sm->prev_key_replay, 0, 1344252726Srpaulo sizeof(sm->prev_key_replay)); 1345252726Srpaulo } 1346252726Srpaulo 1347252726Srpaulo /* 1348252726Srpaulo * Make sure old valid counters are not accepted anymore and 1349252726Srpaulo * do not get copied again. 1350252726Srpaulo */ 1351252726Srpaulo wpa_replay_counter_mark_invalid(sm->key_replay, NULL); 1352214501Srpaulo } 1353214501Srpaulo 1354214501Srpaulo os_free(sm->last_rx_eapol_key); 1355346981Scy sm->last_rx_eapol_key = os_memdup(data, data_len); 1356214501Srpaulo if (sm->last_rx_eapol_key == NULL) 1357214501Srpaulo return; 1358214501Srpaulo sm->last_rx_eapol_key_len = data_len; 1359214501Srpaulo 1360252726Srpaulo sm->rx_eapol_key_secure = !!(key_info & WPA_KEY_INFO_SECURE); 1361214501Srpaulo sm->EAPOLKeyReceived = TRUE; 1362214501Srpaulo sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE); 1363214501Srpaulo sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST); 1364214501Srpaulo os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN); 1365214501Srpaulo wpa_sm_step(sm); 1366214501Srpaulo} 1367214501Srpaulo 1368214501Srpaulo 1369252726Srpaulostatic int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr, 1370252726Srpaulo const u8 *gnonce, u8 *gtk, size_t gtk_len) 1371214501Srpaulo{ 1372346981Scy u8 data[ETH_ALEN + WPA_NONCE_LEN + 8 + WPA_GTK_MAX_LEN]; 1373252726Srpaulo u8 *pos; 1374252726Srpaulo int ret = 0; 1375214501Srpaulo 1376252726Srpaulo /* GTK = PRF-X(GMK, "Group key expansion", 1377252726Srpaulo * AA || GNonce || Time || random data) 1378252726Srpaulo * The example described in the IEEE 802.11 standard uses only AA and 1379252726Srpaulo * GNonce as inputs here. Add some more entropy since this derivation 1380252726Srpaulo * is done only at the Authenticator and as such, does not need to be 1381252726Srpaulo * exactly same. 1382252726Srpaulo */ 1383346981Scy os_memset(data, 0, sizeof(data)); 1384214501Srpaulo os_memcpy(data, addr, ETH_ALEN); 1385214501Srpaulo os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN); 1386252726Srpaulo pos = data + ETH_ALEN + WPA_NONCE_LEN; 1387252726Srpaulo wpa_get_ntp_timestamp(pos); 1388346981Scy#ifdef TEST_FUZZ 1389346981Scy os_memset(pos, 0xef, 8); 1390346981Scy#endif /* TEST_FUZZ */ 1391252726Srpaulo pos += 8; 1392346981Scy if (random_get_bytes(pos, gtk_len) < 0) 1393252726Srpaulo ret = -1; 1394214501Srpaulo 1395346981Scy#ifdef CONFIG_SHA384 1396346981Scy if (sha384_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), 1397346981Scy gtk, gtk_len) < 0) 1398252726Srpaulo ret = -1; 1399346981Scy#else /* CONFIG_SHA384 */ 1400346981Scy#ifdef CONFIG_SHA256 1401346981Scy if (sha256_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), 1402346981Scy gtk, gtk_len) < 0) 1403346981Scy ret = -1; 1404346981Scy#else /* CONFIG_SHA256 */ 1405346981Scy if (sha1_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), 1406346981Scy gtk, gtk_len) < 0) 1407346981Scy ret = -1; 1408346981Scy#endif /* CONFIG_SHA256 */ 1409346981Scy#endif /* CONFIG_SHA384 */ 1410214501Srpaulo 1411351611Scy forced_memzero(data, sizeof(data)); 1412351611Scy 1413252726Srpaulo return ret; 1414214501Srpaulo} 1415214501Srpaulo 1416214501Srpaulo 1417214501Srpaulostatic void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx) 1418214501Srpaulo{ 1419214501Srpaulo struct wpa_authenticator *wpa_auth = eloop_ctx; 1420214501Srpaulo struct wpa_state_machine *sm = timeout_ctx; 1421214501Srpaulo 1422252726Srpaulo sm->pending_1_of_4_timeout = 0; 1423214501Srpaulo wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "EAPOL-Key timeout"); 1424214501Srpaulo sm->TimeoutEvt = TRUE; 1425214501Srpaulo wpa_sm_step(sm); 1426214501Srpaulo} 1427214501Srpaulo 1428214501Srpaulo 1429214501Srpaulovoid __wpa_send_eapol(struct wpa_authenticator *wpa_auth, 1430214501Srpaulo struct wpa_state_machine *sm, int key_info, 1431214501Srpaulo const u8 *key_rsc, const u8 *nonce, 1432214501Srpaulo const u8 *kde, size_t kde_len, 1433214501Srpaulo int keyidx, int encr, int force_version) 1434214501Srpaulo{ 1435214501Srpaulo struct ieee802_1x_hdr *hdr; 1436214501Srpaulo struct wpa_eapol_key *key; 1437281806Srpaulo size_t len, mic_len, keyhdrlen; 1438214501Srpaulo int alg; 1439214501Srpaulo int key_data_len, pad_len = 0; 1440214501Srpaulo u8 *buf, *pos; 1441214501Srpaulo int version, pairwise; 1442214501Srpaulo int i; 1443346981Scy u8 *key_mic, *key_data; 1444214501Srpaulo 1445346981Scy mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len); 1446346981Scy keyhdrlen = sizeof(*key) + mic_len + 2; 1447214501Srpaulo 1448281806Srpaulo len = sizeof(struct ieee802_1x_hdr) + keyhdrlen; 1449281806Srpaulo 1450214501Srpaulo if (force_version) 1451214501Srpaulo version = force_version; 1452346981Scy else if (wpa_use_akm_defined(sm->wpa_key_mgmt)) 1453281806Srpaulo version = WPA_KEY_INFO_TYPE_AKM_DEFINED; 1454346981Scy else if (wpa_use_cmac(sm->wpa_key_mgmt)) 1455214501Srpaulo version = WPA_KEY_INFO_TYPE_AES_128_CMAC; 1456252726Srpaulo else if (sm->pairwise != WPA_CIPHER_TKIP) 1457214501Srpaulo version = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; 1458214501Srpaulo else 1459214501Srpaulo version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; 1460214501Srpaulo 1461281806Srpaulo pairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE); 1462214501Srpaulo 1463214501Srpaulo wpa_printf(MSG_DEBUG, "WPA: Send EAPOL(version=%d secure=%d mic=%d " 1464214501Srpaulo "ack=%d install=%d pairwise=%d kde_len=%lu keyidx=%d " 1465214501Srpaulo "encr=%d)", 1466214501Srpaulo version, 1467214501Srpaulo (key_info & WPA_KEY_INFO_SECURE) ? 1 : 0, 1468214501Srpaulo (key_info & WPA_KEY_INFO_MIC) ? 1 : 0, 1469214501Srpaulo (key_info & WPA_KEY_INFO_ACK) ? 1 : 0, 1470214501Srpaulo (key_info & WPA_KEY_INFO_INSTALL) ? 1 : 0, 1471214501Srpaulo pairwise, (unsigned long) kde_len, keyidx, encr); 1472214501Srpaulo 1473214501Srpaulo key_data_len = kde_len; 1474214501Srpaulo 1475214501Srpaulo if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || 1476346981Scy wpa_use_aes_key_wrap(sm->wpa_key_mgmt) || 1477214501Srpaulo version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) { 1478214501Srpaulo pad_len = key_data_len % 8; 1479214501Srpaulo if (pad_len) 1480214501Srpaulo pad_len = 8 - pad_len; 1481214501Srpaulo key_data_len += pad_len + 8; 1482214501Srpaulo } 1483214501Srpaulo 1484214501Srpaulo len += key_data_len; 1485346981Scy if (!mic_len && encr) 1486346981Scy len += AES_BLOCK_SIZE; 1487214501Srpaulo 1488214501Srpaulo hdr = os_zalloc(len); 1489214501Srpaulo if (hdr == NULL) 1490214501Srpaulo return; 1491214501Srpaulo hdr->version = wpa_auth->conf.eapol_version; 1492214501Srpaulo hdr->type = IEEE802_1X_TYPE_EAPOL_KEY; 1493214501Srpaulo hdr->length = host_to_be16(len - sizeof(*hdr)); 1494214501Srpaulo key = (struct wpa_eapol_key *) (hdr + 1); 1495346981Scy key_mic = (u8 *) (key + 1); 1496281806Srpaulo key_data = ((u8 *) (hdr + 1)) + keyhdrlen; 1497214501Srpaulo 1498214501Srpaulo key->type = sm->wpa == WPA_VERSION_WPA2 ? 1499214501Srpaulo EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; 1500214501Srpaulo key_info |= version; 1501214501Srpaulo if (encr && sm->wpa == WPA_VERSION_WPA2) 1502214501Srpaulo key_info |= WPA_KEY_INFO_ENCR_KEY_DATA; 1503214501Srpaulo if (sm->wpa != WPA_VERSION_WPA2) 1504214501Srpaulo key_info |= keyidx << WPA_KEY_INFO_KEY_INDEX_SHIFT; 1505214501Srpaulo WPA_PUT_BE16(key->key_info, key_info); 1506214501Srpaulo 1507214501Srpaulo alg = pairwise ? sm->pairwise : wpa_auth->conf.wpa_group; 1508346981Scy if (sm->wpa == WPA_VERSION_WPA2 && !pairwise) 1509214501Srpaulo WPA_PUT_BE16(key->key_length, 0); 1510346981Scy else 1511346981Scy WPA_PUT_BE16(key->key_length, wpa_cipher_key_len(alg)); 1512214501Srpaulo 1513214501Srpaulo for (i = RSNA_MAX_EAPOL_RETRIES - 1; i > 0; i--) { 1514214501Srpaulo sm->key_replay[i].valid = sm->key_replay[i - 1].valid; 1515214501Srpaulo os_memcpy(sm->key_replay[i].counter, 1516214501Srpaulo sm->key_replay[i - 1].counter, 1517214501Srpaulo WPA_REPLAY_COUNTER_LEN); 1518214501Srpaulo } 1519214501Srpaulo inc_byte_array(sm->key_replay[0].counter, WPA_REPLAY_COUNTER_LEN); 1520214501Srpaulo os_memcpy(key->replay_counter, sm->key_replay[0].counter, 1521214501Srpaulo WPA_REPLAY_COUNTER_LEN); 1522281806Srpaulo wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter", 1523281806Srpaulo key->replay_counter, WPA_REPLAY_COUNTER_LEN); 1524214501Srpaulo sm->key_replay[0].valid = TRUE; 1525214501Srpaulo 1526214501Srpaulo if (nonce) 1527214501Srpaulo os_memcpy(key->key_nonce, nonce, WPA_NONCE_LEN); 1528214501Srpaulo 1529214501Srpaulo if (key_rsc) 1530214501Srpaulo os_memcpy(key->key_rsc, key_rsc, WPA_KEY_RSC_LEN); 1531214501Srpaulo 1532214501Srpaulo if (kde && !encr) { 1533281806Srpaulo os_memcpy(key_data, kde, kde_len); 1534346981Scy WPA_PUT_BE16(key_mic + mic_len, kde_len); 1535346981Scy#ifdef CONFIG_FILS 1536346981Scy } else if (!mic_len && kde) { 1537346981Scy const u8 *aad[1]; 1538346981Scy size_t aad_len[1]; 1539346981Scy 1540346981Scy WPA_PUT_BE16(key_mic, AES_BLOCK_SIZE + kde_len); 1541346981Scy wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data", 1542346981Scy kde, kde_len); 1543346981Scy 1544346981Scy wpa_hexdump_key(MSG_DEBUG, "WPA: KEK", 1545346981Scy sm->PTK.kek, sm->PTK.kek_len); 1546346981Scy /* AES-SIV AAD from EAPOL protocol version field (inclusive) to 1547346981Scy * to Key Data (exclusive). */ 1548346981Scy aad[0] = (u8 *) hdr; 1549346981Scy aad_len[0] = key_mic + 2 - (u8 *) hdr; 1550346981Scy if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len, kde, kde_len, 1551346981Scy 1, aad, aad_len, key_mic + 2) < 0) { 1552346981Scy wpa_printf(MSG_DEBUG, "WPA: AES-SIV encryption failed"); 1553346981Scy return; 1554346981Scy } 1555346981Scy 1556346981Scy wpa_hexdump(MSG_DEBUG, "WPA: Encrypted Key Data from SIV", 1557346981Scy key_mic + 2, AES_BLOCK_SIZE + kde_len); 1558346981Scy#endif /* CONFIG_FILS */ 1559214501Srpaulo } else if (encr && kde) { 1560214501Srpaulo buf = os_zalloc(key_data_len); 1561214501Srpaulo if (buf == NULL) { 1562214501Srpaulo os_free(hdr); 1563214501Srpaulo return; 1564214501Srpaulo } 1565214501Srpaulo pos = buf; 1566214501Srpaulo os_memcpy(pos, kde, kde_len); 1567214501Srpaulo pos += kde_len; 1568214501Srpaulo 1569214501Srpaulo if (pad_len) 1570214501Srpaulo *pos++ = 0xdd; 1571214501Srpaulo 1572214501Srpaulo wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data", 1573214501Srpaulo buf, key_data_len); 1574214501Srpaulo if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || 1575346981Scy wpa_use_aes_key_wrap(sm->wpa_key_mgmt) || 1576214501Srpaulo version == WPA_KEY_INFO_TYPE_AES_128_CMAC) { 1577346981Scy wpa_printf(MSG_DEBUG, 1578346981Scy "WPA: Encrypt Key Data using AES-WRAP (KEK length %u)", 1579346981Scy (unsigned int) sm->PTK.kek_len); 1580281806Srpaulo if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len, 1581281806Srpaulo (key_data_len - 8) / 8, buf, key_data)) { 1582214501Srpaulo os_free(hdr); 1583214501Srpaulo os_free(buf); 1584214501Srpaulo return; 1585214501Srpaulo } 1586346981Scy WPA_PUT_BE16(key_mic + mic_len, key_data_len); 1587289549Srpaulo#ifndef CONFIG_NO_RC4 1588281806Srpaulo } else if (sm->PTK.kek_len == 16) { 1589214501Srpaulo u8 ek[32]; 1590346981Scy 1591346981Scy wpa_printf(MSG_DEBUG, 1592346981Scy "WPA: Encrypt Key Data using RC4"); 1593214501Srpaulo os_memcpy(key->key_iv, 1594214501Srpaulo sm->group->Counter + WPA_NONCE_LEN - 16, 16); 1595214501Srpaulo inc_byte_array(sm->group->Counter, WPA_NONCE_LEN); 1596214501Srpaulo os_memcpy(ek, key->key_iv, 16); 1597281806Srpaulo os_memcpy(ek + 16, sm->PTK.kek, sm->PTK.kek_len); 1598281806Srpaulo os_memcpy(key_data, buf, key_data_len); 1599281806Srpaulo rc4_skip(ek, 32, 256, key_data, key_data_len); 1600346981Scy WPA_PUT_BE16(key_mic + mic_len, key_data_len); 1601289549Srpaulo#endif /* CONFIG_NO_RC4 */ 1602281806Srpaulo } else { 1603281806Srpaulo os_free(hdr); 1604281806Srpaulo os_free(buf); 1605281806Srpaulo return; 1606214501Srpaulo } 1607214501Srpaulo os_free(buf); 1608214501Srpaulo } 1609214501Srpaulo 1610214501Srpaulo if (key_info & WPA_KEY_INFO_MIC) { 1611346981Scy if (!sm->PTK_valid || !mic_len) { 1612214501Srpaulo wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, 1613214501Srpaulo "PTK not valid when sending EAPOL-Key " 1614214501Srpaulo "frame"); 1615214501Srpaulo os_free(hdr); 1616214501Srpaulo return; 1617214501Srpaulo } 1618281806Srpaulo 1619346981Scy if (wpa_eapol_key_mic(sm->PTK.kck, sm->PTK.kck_len, 1620346981Scy sm->wpa_key_mgmt, version, 1621346981Scy (u8 *) hdr, len, key_mic) < 0) { 1622346981Scy os_free(hdr); 1623346981Scy return; 1624346981Scy } 1625281806Srpaulo#ifdef CONFIG_TESTING_OPTIONS 1626281806Srpaulo if (!pairwise && 1627281806Srpaulo wpa_auth->conf.corrupt_gtk_rekey_mic_probability > 0.0 && 1628281806Srpaulo drand48() < 1629281806Srpaulo wpa_auth->conf.corrupt_gtk_rekey_mic_probability) { 1630281806Srpaulo wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 1631281806Srpaulo "Corrupting group EAPOL-Key Key MIC"); 1632281806Srpaulo key_mic[0]++; 1633281806Srpaulo } 1634281806Srpaulo#endif /* CONFIG_TESTING_OPTIONS */ 1635214501Srpaulo } 1636214501Srpaulo 1637214501Srpaulo wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, 1638214501Srpaulo 1); 1639214501Srpaulo wpa_auth_send_eapol(wpa_auth, sm->addr, (u8 *) hdr, len, 1640214501Srpaulo sm->pairwise_set); 1641214501Srpaulo os_free(hdr); 1642214501Srpaulo} 1643214501Srpaulo 1644214501Srpaulo 1645214501Srpaulostatic void wpa_send_eapol(struct wpa_authenticator *wpa_auth, 1646214501Srpaulo struct wpa_state_machine *sm, int key_info, 1647214501Srpaulo const u8 *key_rsc, const u8 *nonce, 1648214501Srpaulo const u8 *kde, size_t kde_len, 1649214501Srpaulo int keyidx, int encr) 1650214501Srpaulo{ 1651214501Srpaulo int timeout_ms; 1652214501Srpaulo int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE; 1653346981Scy u32 ctr; 1654214501Srpaulo 1655214501Srpaulo if (sm == NULL) 1656214501Srpaulo return; 1657214501Srpaulo 1658214501Srpaulo __wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len, 1659214501Srpaulo keyidx, encr, 0); 1660214501Srpaulo 1661214501Srpaulo ctr = pairwise ? sm->TimeoutCtr : sm->GTimeoutCtr; 1662252726Srpaulo if (ctr == 1 && wpa_auth->conf.tx_status) 1663252726Srpaulo timeout_ms = pairwise ? eapol_key_timeout_first : 1664252726Srpaulo eapol_key_timeout_first_group; 1665214501Srpaulo else 1666214501Srpaulo timeout_ms = eapol_key_timeout_subseq; 1667346981Scy if (wpa_auth->conf.wpa_disable_eapol_key_retries && 1668346981Scy (!pairwise || (key_info & WPA_KEY_INFO_MIC))) 1669346981Scy timeout_ms = eapol_key_timeout_no_retrans; 1670252726Srpaulo if (pairwise && ctr == 1 && !(key_info & WPA_KEY_INFO_MIC)) 1671252726Srpaulo sm->pending_1_of_4_timeout = 1; 1672346981Scy#ifdef TEST_FUZZ 1673346981Scy timeout_ms = 1; 1674346981Scy#endif /* TEST_FUZZ */ 1675252726Srpaulo wpa_printf(MSG_DEBUG, "WPA: Use EAPOL-Key timeout of %u ms (retry " 1676346981Scy "counter %u)", timeout_ms, ctr); 1677214501Srpaulo eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000, 1678214501Srpaulo wpa_send_eapol_timeout, wpa_auth, sm); 1679214501Srpaulo} 1680214501Srpaulo 1681214501Srpaulo 1682346981Scystatic int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK, 1683346981Scy u8 *data, size_t data_len) 1684214501Srpaulo{ 1685214501Srpaulo struct ieee802_1x_hdr *hdr; 1686214501Srpaulo struct wpa_eapol_key *key; 1687214501Srpaulo u16 key_info; 1688214501Srpaulo int ret = 0; 1689346981Scy u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN], *mic_pos; 1690346981Scy size_t mic_len = wpa_mic_len(akmp, pmk_len); 1691214501Srpaulo 1692214501Srpaulo if (data_len < sizeof(*hdr) + sizeof(*key)) 1693214501Srpaulo return -1; 1694214501Srpaulo 1695214501Srpaulo hdr = (struct ieee802_1x_hdr *) data; 1696214501Srpaulo key = (struct wpa_eapol_key *) (hdr + 1); 1697346981Scy mic_pos = (u8 *) (key + 1); 1698214501Srpaulo key_info = WPA_GET_BE16(key->key_info); 1699346981Scy os_memcpy(mic, mic_pos, mic_len); 1700346981Scy os_memset(mic_pos, 0, mic_len); 1701281806Srpaulo if (wpa_eapol_key_mic(PTK->kck, PTK->kck_len, akmp, 1702281806Srpaulo key_info & WPA_KEY_INFO_TYPE_MASK, 1703346981Scy data, data_len, mic_pos) || 1704346981Scy os_memcmp_const(mic, mic_pos, mic_len) != 0) 1705214501Srpaulo ret = -1; 1706346981Scy os_memcpy(mic_pos, mic, mic_len); 1707214501Srpaulo return ret; 1708214501Srpaulo} 1709214501Srpaulo 1710214501Srpaulo 1711214501Srpaulovoid wpa_remove_ptk(struct wpa_state_machine *sm) 1712214501Srpaulo{ 1713214501Srpaulo sm->PTK_valid = FALSE; 1714214501Srpaulo os_memset(&sm->PTK, 0, sizeof(sm->PTK)); 1715346981Scy if (wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, NULL, 1716346981Scy 0)) 1717346981Scy wpa_printf(MSG_DEBUG, 1718346981Scy "RSN: PTK removal from the driver failed"); 1719214501Srpaulo sm->pairwise_set = FALSE; 1720214501Srpaulo eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); 1721214501Srpaulo} 1722214501Srpaulo 1723214501Srpaulo 1724289549Srpauloint wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) 1725214501Srpaulo{ 1726214501Srpaulo int remove_ptk = 1; 1727214501Srpaulo 1728214501Srpaulo if (sm == NULL) 1729214501Srpaulo return -1; 1730214501Srpaulo 1731214501Srpaulo wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 1732214501Srpaulo "event %d notification", event); 1733214501Srpaulo 1734214501Srpaulo switch (event) { 1735214501Srpaulo case WPA_AUTH: 1736281806Srpaulo#ifdef CONFIG_MESH 1737281806Srpaulo /* PTKs are derived through AMPE */ 1738281806Srpaulo if (wpa_auth_start_ampe(sm->wpa_auth, sm->addr)) { 1739281806Srpaulo /* not mesh */ 1740281806Srpaulo break; 1741281806Srpaulo } 1742281806Srpaulo return 0; 1743281806Srpaulo#endif /* CONFIG_MESH */ 1744214501Srpaulo case WPA_ASSOC: 1745214501Srpaulo break; 1746214501Srpaulo case WPA_DEAUTH: 1747214501Srpaulo case WPA_DISASSOC: 1748214501Srpaulo sm->DeauthenticationRequest = TRUE; 1749346981Scy#ifdef CONFIG_IEEE80211R_AP 1750346981Scy os_memset(sm->PMK, 0, sizeof(sm->PMK)); 1751346981Scy sm->pmk_len = 0; 1752346981Scy os_memset(sm->xxkey, 0, sizeof(sm->xxkey)); 1753346981Scy sm->xxkey_len = 0; 1754346981Scy os_memset(sm->pmk_r1, 0, sizeof(sm->pmk_r1)); 1755346981Scy sm->pmk_r1_len = 0; 1756346981Scy#endif /* CONFIG_IEEE80211R_AP */ 1757214501Srpaulo break; 1758214501Srpaulo case WPA_REAUTH: 1759214501Srpaulo case WPA_REAUTH_EAPOL: 1760214501Srpaulo if (!sm->started) { 1761214501Srpaulo /* 1762214501Srpaulo * When using WPS, we may end up here if the STA 1763214501Srpaulo * manages to re-associate without the previous STA 1764214501Srpaulo * entry getting removed. Consequently, we need to make 1765214501Srpaulo * sure that the WPA state machines gets initialized 1766214501Srpaulo * properly at this point. 1767214501Srpaulo */ 1768214501Srpaulo wpa_printf(MSG_DEBUG, "WPA state machine had not been " 1769214501Srpaulo "started - initialize now"); 1770214501Srpaulo sm->started = 1; 1771214501Srpaulo sm->Init = TRUE; 1772214501Srpaulo if (wpa_sm_step(sm) == 1) 1773214501Srpaulo return 1; /* should not really happen */ 1774214501Srpaulo sm->Init = FALSE; 1775214501Srpaulo sm->AuthenticationRequest = TRUE; 1776214501Srpaulo break; 1777214501Srpaulo } 1778214501Srpaulo if (sm->GUpdateStationKeys) { 1779214501Srpaulo /* 1780214501Srpaulo * Reauthentication cancels the pending group key 1781214501Srpaulo * update for this STA. 1782214501Srpaulo */ 1783214501Srpaulo sm->group->GKeyDoneStations--; 1784214501Srpaulo sm->GUpdateStationKeys = FALSE; 1785214501Srpaulo sm->PtkGroupInit = TRUE; 1786214501Srpaulo } 1787214501Srpaulo sm->ReAuthenticationRequest = TRUE; 1788214501Srpaulo break; 1789214501Srpaulo case WPA_ASSOC_FT: 1790346981Scy#ifdef CONFIG_IEEE80211R_AP 1791214501Srpaulo wpa_printf(MSG_DEBUG, "FT: Retry PTK configuration " 1792214501Srpaulo "after association"); 1793214501Srpaulo wpa_ft_install_ptk(sm); 1794214501Srpaulo 1795214501Srpaulo /* Using FT protocol, not WPA auth state machine */ 1796214501Srpaulo sm->ft_completed = 1; 1797346981Scy wpa_auth_set_ptk_rekey_timer(sm); 1798214501Srpaulo return 0; 1799346981Scy#else /* CONFIG_IEEE80211R_AP */ 1800214501Srpaulo break; 1801346981Scy#endif /* CONFIG_IEEE80211R_AP */ 1802346981Scy case WPA_ASSOC_FILS: 1803346981Scy#ifdef CONFIG_FILS 1804346981Scy wpa_printf(MSG_DEBUG, 1805346981Scy "FILS: TK configuration after association"); 1806346981Scy fils_set_tk(sm); 1807346981Scy sm->fils_completed = 1; 1808346981Scy return 0; 1809346981Scy#else /* CONFIG_FILS */ 1810346981Scy break; 1811346981Scy#endif /* CONFIG_FILS */ 1812337817Scy case WPA_DRV_STA_REMOVED: 1813337817Scy sm->tk_already_set = FALSE; 1814337817Scy return 0; 1815214501Srpaulo } 1816214501Srpaulo 1817346981Scy#ifdef CONFIG_IEEE80211R_AP 1818214501Srpaulo sm->ft_completed = 0; 1819346981Scy#endif /* CONFIG_IEEE80211R_AP */ 1820214501Srpaulo 1821214501Srpaulo#ifdef CONFIG_IEEE80211W 1822214501Srpaulo if (sm->mgmt_frame_prot && event == WPA_AUTH) 1823214501Srpaulo remove_ptk = 0; 1824214501Srpaulo#endif /* CONFIG_IEEE80211W */ 1825346981Scy#ifdef CONFIG_FILS 1826346981Scy if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) && 1827346981Scy (event == WPA_AUTH || event == WPA_ASSOC)) 1828346981Scy remove_ptk = 0; 1829346981Scy#endif /* CONFIG_FILS */ 1830214501Srpaulo 1831214501Srpaulo if (remove_ptk) { 1832214501Srpaulo sm->PTK_valid = FALSE; 1833214501Srpaulo os_memset(&sm->PTK, 0, sizeof(sm->PTK)); 1834214501Srpaulo 1835214501Srpaulo if (event != WPA_REAUTH_EAPOL) 1836214501Srpaulo wpa_remove_ptk(sm); 1837214501Srpaulo } 1838214501Srpaulo 1839289549Srpaulo if (sm->in_step_loop) { 1840289549Srpaulo /* 1841289549Srpaulo * wpa_sm_step() is already running - avoid recursive call to 1842289549Srpaulo * it by making the existing loop process the new update. 1843289549Srpaulo */ 1844289549Srpaulo sm->changed = TRUE; 1845289549Srpaulo return 0; 1846289549Srpaulo } 1847214501Srpaulo return wpa_sm_step(sm); 1848214501Srpaulo} 1849214501Srpaulo 1850214501Srpaulo 1851214501SrpauloSM_STATE(WPA_PTK, INITIALIZE) 1852214501Srpaulo{ 1853214501Srpaulo SM_ENTRY_MA(WPA_PTK, INITIALIZE, wpa_ptk); 1854214501Srpaulo if (sm->Init) { 1855214501Srpaulo /* Init flag is not cleared here, so avoid busy 1856214501Srpaulo * loop by claiming nothing changed. */ 1857214501Srpaulo sm->changed = FALSE; 1858214501Srpaulo } 1859214501Srpaulo 1860214501Srpaulo sm->keycount = 0; 1861214501Srpaulo if (sm->GUpdateStationKeys) 1862214501Srpaulo sm->group->GKeyDoneStations--; 1863214501Srpaulo sm->GUpdateStationKeys = FALSE; 1864214501Srpaulo if (sm->wpa == WPA_VERSION_WPA) 1865214501Srpaulo sm->PInitAKeys = FALSE; 1866214501Srpaulo if (1 /* Unicast cipher supported AND (ESS OR ((IBSS or WDS) and 1867214501Srpaulo * Local AA > Remote AA)) */) { 1868214501Srpaulo sm->Pair = TRUE; 1869214501Srpaulo } 1870214501Srpaulo wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 0); 1871214501Srpaulo wpa_remove_ptk(sm); 1872214501Srpaulo wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 0); 1873214501Srpaulo sm->TimeoutCtr = 0; 1874346981Scy if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) || 1875346981Scy sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP || 1876346981Scy sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) { 1877214501Srpaulo wpa_auth_set_eapol(sm->wpa_auth, sm->addr, 1878214501Srpaulo WPA_EAPOL_authorized, 0); 1879214501Srpaulo } 1880214501Srpaulo} 1881214501Srpaulo 1882214501Srpaulo 1883214501SrpauloSM_STATE(WPA_PTK, DISCONNECT) 1884214501Srpaulo{ 1885346981Scy u16 reason = sm->disconnect_reason; 1886346981Scy 1887214501Srpaulo SM_ENTRY_MA(WPA_PTK, DISCONNECT, wpa_ptk); 1888214501Srpaulo sm->Disconnect = FALSE; 1889346981Scy sm->disconnect_reason = 0; 1890346981Scy if (!reason) 1891346981Scy reason = WLAN_REASON_PREV_AUTH_NOT_VALID; 1892346981Scy wpa_sta_disconnect(sm->wpa_auth, sm->addr, reason); 1893214501Srpaulo} 1894214501Srpaulo 1895214501Srpaulo 1896214501SrpauloSM_STATE(WPA_PTK, DISCONNECTED) 1897214501Srpaulo{ 1898214501Srpaulo SM_ENTRY_MA(WPA_PTK, DISCONNECTED, wpa_ptk); 1899214501Srpaulo sm->DeauthenticationRequest = FALSE; 1900214501Srpaulo} 1901214501Srpaulo 1902214501Srpaulo 1903214501SrpauloSM_STATE(WPA_PTK, AUTHENTICATION) 1904214501Srpaulo{ 1905214501Srpaulo SM_ENTRY_MA(WPA_PTK, AUTHENTICATION, wpa_ptk); 1906214501Srpaulo os_memset(&sm->PTK, 0, sizeof(sm->PTK)); 1907214501Srpaulo sm->PTK_valid = FALSE; 1908214501Srpaulo wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portControl_Auto, 1909214501Srpaulo 1); 1910214501Srpaulo wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 1); 1911214501Srpaulo sm->AuthenticationRequest = FALSE; 1912214501Srpaulo} 1913214501Srpaulo 1914214501Srpaulo 1915252726Srpaulostatic void wpa_group_ensure_init(struct wpa_authenticator *wpa_auth, 1916252726Srpaulo struct wpa_group *group) 1917252726Srpaulo{ 1918252726Srpaulo if (group->first_sta_seen) 1919252726Srpaulo return; 1920252726Srpaulo /* 1921252726Srpaulo * System has run bit further than at the time hostapd was started 1922252726Srpaulo * potentially very early during boot up. This provides better chances 1923252726Srpaulo * of collecting more randomness on embedded systems. Re-initialize the 1924252726Srpaulo * GMK and Counter here to improve their strength if there was not 1925252726Srpaulo * enough entropy available immediately after system startup. 1926252726Srpaulo */ 1927252726Srpaulo wpa_printf(MSG_DEBUG, "WPA: Re-initialize GMK/Counter on first " 1928252726Srpaulo "station"); 1929252726Srpaulo if (random_pool_ready() != 1) { 1930252726Srpaulo wpa_printf(MSG_INFO, "WPA: Not enough entropy in random pool " 1931252726Srpaulo "to proceed - reject first 4-way handshake"); 1932252726Srpaulo group->reject_4way_hs_for_entropy = TRUE; 1933252726Srpaulo } else { 1934252726Srpaulo group->first_sta_seen = TRUE; 1935252726Srpaulo group->reject_4way_hs_for_entropy = FALSE; 1936252726Srpaulo } 1937252726Srpaulo 1938289549Srpaulo if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0 || 1939289549Srpaulo wpa_gtk_update(wpa_auth, group) < 0 || 1940289549Srpaulo wpa_group_config_group_keys(wpa_auth, group) < 0) { 1941289549Srpaulo wpa_printf(MSG_INFO, "WPA: GMK/GTK setup failed"); 1942289549Srpaulo group->first_sta_seen = FALSE; 1943289549Srpaulo group->reject_4way_hs_for_entropy = TRUE; 1944289549Srpaulo } 1945252726Srpaulo} 1946252726Srpaulo 1947252726Srpaulo 1948214501SrpauloSM_STATE(WPA_PTK, AUTHENTICATION2) 1949214501Srpaulo{ 1950214501Srpaulo SM_ENTRY_MA(WPA_PTK, AUTHENTICATION2, wpa_ptk); 1951252726Srpaulo 1952252726Srpaulo wpa_group_ensure_init(sm->wpa_auth, sm->group); 1953281806Srpaulo sm->ReAuthenticationRequest = FALSE; 1954252726Srpaulo 1955252726Srpaulo /* 1956252726Srpaulo * Definition of ANonce selection in IEEE Std 802.11i-2004 is somewhat 1957252726Srpaulo * ambiguous. The Authenticator state machine uses a counter that is 1958252726Srpaulo * incremented by one for each 4-way handshake. However, the security 1959252726Srpaulo * analysis of 4-way handshake points out that unpredictable nonces 1960252726Srpaulo * help in preventing precomputation attacks. Instead of the state 1961252726Srpaulo * machine definition, use an unpredictable nonce value here to provide 1962252726Srpaulo * stronger protection against potential precomputation attacks. 1963252726Srpaulo */ 1964252726Srpaulo if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) { 1965252726Srpaulo wpa_printf(MSG_ERROR, "WPA: Failed to get random data for " 1966252726Srpaulo "ANonce."); 1967281806Srpaulo sm->Disconnect = TRUE; 1968252726Srpaulo return; 1969252726Srpaulo } 1970252726Srpaulo wpa_hexdump(MSG_DEBUG, "WPA: Assign ANonce", sm->ANonce, 1971252726Srpaulo WPA_NONCE_LEN); 1972214501Srpaulo /* IEEE 802.11i does not clear TimeoutCtr here, but this is more 1973214501Srpaulo * logical place than INITIALIZE since AUTHENTICATION2 can be 1974214501Srpaulo * re-entered on ReAuthenticationRequest without going through 1975214501Srpaulo * INITIALIZE. */ 1976214501Srpaulo sm->TimeoutCtr = 0; 1977214501Srpaulo} 1978214501Srpaulo 1979214501Srpaulo 1980324697Sgordonstatic int wpa_auth_sm_ptk_update(struct wpa_state_machine *sm) 1981324697Sgordon{ 1982324697Sgordon if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) { 1983324697Sgordon wpa_printf(MSG_ERROR, 1984324697Sgordon "WPA: Failed to get random data for ANonce"); 1985324697Sgordon sm->Disconnect = TRUE; 1986324697Sgordon return -1; 1987324697Sgordon } 1988324697Sgordon wpa_hexdump(MSG_DEBUG, "WPA: Assign new ANonce", sm->ANonce, 1989324697Sgordon WPA_NONCE_LEN); 1990324697Sgordon sm->TimeoutCtr = 0; 1991324697Sgordon return 0; 1992324697Sgordon} 1993324697Sgordon 1994324697Sgordon 1995214501SrpauloSM_STATE(WPA_PTK, INITPMK) 1996214501Srpaulo{ 1997214501Srpaulo u8 msk[2 * PMK_LEN]; 1998214501Srpaulo size_t len = 2 * PMK_LEN; 1999214501Srpaulo 2000214501Srpaulo SM_ENTRY_MA(WPA_PTK, INITPMK, wpa_ptk); 2001346981Scy#ifdef CONFIG_IEEE80211R_AP 2002214501Srpaulo sm->xxkey_len = 0; 2003346981Scy#endif /* CONFIG_IEEE80211R_AP */ 2004214501Srpaulo if (sm->pmksa) { 2005214501Srpaulo wpa_printf(MSG_DEBUG, "WPA: PMK from PMKSA cache"); 2006337817Scy os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len); 2007337817Scy sm->pmk_len = sm->pmksa->pmk_len; 2008346981Scy#ifdef CONFIG_DPP 2009346981Scy } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) { 2010346981Scy wpa_printf(MSG_DEBUG, 2011346981Scy "DPP: No PMKSA cache entry for STA - reject connection"); 2012346981Scy sm->Disconnect = TRUE; 2013346981Scy sm->disconnect_reason = WLAN_REASON_INVALID_PMKID; 2014346981Scy return; 2015346981Scy#endif /* CONFIG_DPP */ 2016214501Srpaulo } else if (wpa_auth_get_msk(sm->wpa_auth, sm->addr, msk, &len) == 0) { 2017337817Scy unsigned int pmk_len; 2018337817Scy 2019346981Scy if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) 2020337817Scy pmk_len = PMK_LEN_SUITE_B_192; 2021337817Scy else 2022337817Scy pmk_len = PMK_LEN; 2023214501Srpaulo wpa_printf(MSG_DEBUG, "WPA: PMK from EAPOL state machine " 2024337817Scy "(MSK len=%lu PMK len=%u)", (unsigned long) len, 2025337817Scy pmk_len); 2026337817Scy if (len < pmk_len) { 2027337817Scy wpa_printf(MSG_DEBUG, 2028337817Scy "WPA: MSK not long enough (%u) to create PMK (%u)", 2029337817Scy (unsigned int) len, (unsigned int) pmk_len); 2030337817Scy sm->Disconnect = TRUE; 2031337817Scy return; 2032337817Scy } 2033337817Scy os_memcpy(sm->PMK, msk, pmk_len); 2034337817Scy sm->pmk_len = pmk_len; 2035346981Scy#ifdef CONFIG_IEEE80211R_AP 2036214501Srpaulo if (len >= 2 * PMK_LEN) { 2037346981Scy if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) { 2038346981Scy os_memcpy(sm->xxkey, msk, SHA384_MAC_LEN); 2039346981Scy sm->xxkey_len = SHA384_MAC_LEN; 2040346981Scy } else { 2041346981Scy os_memcpy(sm->xxkey, msk + PMK_LEN, PMK_LEN); 2042346981Scy sm->xxkey_len = PMK_LEN; 2043346981Scy } 2044214501Srpaulo } 2045346981Scy#endif /* CONFIG_IEEE80211R_AP */ 2046214501Srpaulo } else { 2047281806Srpaulo wpa_printf(MSG_DEBUG, "WPA: Could not get PMK, get_msk: %p", 2048346981Scy sm->wpa_auth->cb->get_msk); 2049281806Srpaulo sm->Disconnect = TRUE; 2050281806Srpaulo return; 2051214501Srpaulo } 2052351611Scy forced_memzero(msk, sizeof(msk)); 2053214501Srpaulo 2054214501Srpaulo sm->req_replay_counter_used = 0; 2055214501Srpaulo /* IEEE 802.11i does not set keyRun to FALSE, but not doing this 2056214501Srpaulo * will break reauthentication since EAPOL state machines may not be 2057214501Srpaulo * get into AUTHENTICATING state that clears keyRun before WPA state 2058214501Srpaulo * machine enters AUTHENTICATION2 state and goes immediately to INITPMK 2059214501Srpaulo * state and takes PMK from the previously used AAA Key. This will 2060214501Srpaulo * eventually fail in 4-Way Handshake because Supplicant uses PMK 2061214501Srpaulo * derived from the new AAA Key. Setting keyRun = FALSE here seems to 2062214501Srpaulo * be good workaround for this issue. */ 2063214501Srpaulo wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun, 0); 2064214501Srpaulo} 2065214501Srpaulo 2066214501Srpaulo 2067214501SrpauloSM_STATE(WPA_PTK, INITPSK) 2068214501Srpaulo{ 2069214501Srpaulo const u8 *psk; 2070346981Scy size_t psk_len; 2071346981Scy 2072214501Srpaulo SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk); 2073346981Scy psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL, 2074346981Scy &psk_len, NULL); 2075214501Srpaulo if (psk) { 2076346981Scy os_memcpy(sm->PMK, psk, psk_len); 2077346981Scy sm->pmk_len = psk_len; 2078346981Scy#ifdef CONFIG_IEEE80211R_AP 2079214501Srpaulo os_memcpy(sm->xxkey, psk, PMK_LEN); 2080214501Srpaulo sm->xxkey_len = PMK_LEN; 2081346981Scy#endif /* CONFIG_IEEE80211R_AP */ 2082214501Srpaulo } 2083346981Scy#ifdef CONFIG_SAE 2084346981Scy if (wpa_auth_uses_sae(sm) && sm->pmksa) { 2085346981Scy wpa_printf(MSG_DEBUG, "SAE: PMK from PMKSA cache"); 2086346981Scy os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len); 2087346981Scy sm->pmk_len = sm->pmksa->pmk_len; 2088346981Scy#ifdef CONFIG_IEEE80211R_AP 2089346981Scy os_memcpy(sm->xxkey, sm->pmksa->pmk, sm->pmksa->pmk_len); 2090346981Scy sm->xxkey_len = sm->pmksa->pmk_len; 2091346981Scy#endif /* CONFIG_IEEE80211R_AP */ 2092346981Scy } 2093346981Scy#endif /* CONFIG_SAE */ 2094214501Srpaulo sm->req_replay_counter_used = 0; 2095214501Srpaulo} 2096214501Srpaulo 2097214501Srpaulo 2098214501SrpauloSM_STATE(WPA_PTK, PTKSTART) 2099214501Srpaulo{ 2100214501Srpaulo u8 buf[2 + RSN_SELECTOR_LEN + PMKID_LEN], *pmkid = NULL; 2101214501Srpaulo size_t pmkid_len = 0; 2102214501Srpaulo 2103214501Srpaulo SM_ENTRY_MA(WPA_PTK, PTKSTART, wpa_ptk); 2104214501Srpaulo sm->PTKRequest = FALSE; 2105214501Srpaulo sm->TimeoutEvt = FALSE; 2106281806Srpaulo sm->alt_snonce_valid = FALSE; 2107214501Srpaulo 2108214501Srpaulo sm->TimeoutCtr++; 2109346981Scy if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) { 2110214501Srpaulo /* No point in sending the EAPOL-Key - we will disconnect 2111214501Srpaulo * immediately following this. */ 2112214501Srpaulo return; 2113214501Srpaulo } 2114214501Srpaulo 2115214501Srpaulo wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 2116214501Srpaulo "sending 1/4 msg of 4-Way Handshake"); 2117214501Srpaulo /* 2118346981Scy * For infrastructure BSS cases, it is better for the AP not to include 2119346981Scy * the PMKID KDE in EAPOL-Key msg 1/4 since it could be used to initiate 2120346981Scy * offline search for the passphrase/PSK without having to be able to 2121346981Scy * capture a 4-way handshake from a STA that has access to the network. 2122346981Scy * 2123346981Scy * For IBSS cases, addition of PMKID KDE could be considered even with 2124346981Scy * WPA2-PSK cases that use multiple PSKs, but only if there is a single 2125346981Scy * possible PSK for this STA. However, this should not be done unless 2126346981Scy * there is support for using that information on the supplicant side. 2127346981Scy * The concern about exposing PMKID unnecessarily in infrastructure BSS 2128346981Scy * cases would also apply here, but at least in the IBSS case, this 2129346981Scy * would cover a potential real use case. 2130214501Srpaulo */ 2131214501Srpaulo if (sm->wpa == WPA_VERSION_WPA2 && 2132346981Scy (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) || 2133346981Scy (sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && sm->pmksa) || 2134346981Scy wpa_key_mgmt_sae(sm->wpa_key_mgmt)) && 2135281806Srpaulo sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN) { 2136214501Srpaulo pmkid = buf; 2137214501Srpaulo pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN; 2138214501Srpaulo pmkid[0] = WLAN_EID_VENDOR_SPECIFIC; 2139214501Srpaulo pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN; 2140214501Srpaulo RSN_SELECTOR_PUT(&pmkid[2], RSN_KEY_DATA_PMKID); 2141281806Srpaulo if (sm->pmksa) { 2142346981Scy wpa_hexdump(MSG_DEBUG, 2143346981Scy "RSN: Message 1/4 PMKID from PMKSA entry", 2144346981Scy sm->pmksa->pmkid, PMKID_LEN); 2145214501Srpaulo os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN], 2146214501Srpaulo sm->pmksa->pmkid, PMKID_LEN); 2147281806Srpaulo } else if (wpa_key_mgmt_suite_b(sm->wpa_key_mgmt)) { 2148281806Srpaulo /* No KCK available to derive PMKID */ 2149346981Scy wpa_printf(MSG_DEBUG, 2150346981Scy "RSN: No KCK available to derive PMKID for message 1/4"); 2151281806Srpaulo pmkid = NULL; 2152346981Scy#ifdef CONFIG_FILS 2153346981Scy } else if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) { 2154346981Scy if (sm->pmkid_set) { 2155346981Scy wpa_hexdump(MSG_DEBUG, 2156346981Scy "RSN: Message 1/4 PMKID from FILS/ERP", 2157346981Scy sm->pmkid, PMKID_LEN); 2158346981Scy os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN], 2159346981Scy sm->pmkid, PMKID_LEN); 2160346981Scy } else { 2161346981Scy /* No PMKID available */ 2162346981Scy wpa_printf(MSG_DEBUG, 2163346981Scy "RSN: No FILS/ERP PMKID available for message 1/4"); 2164346981Scy pmkid = NULL; 2165346981Scy } 2166346981Scy#endif /* CONFIG_FILS */ 2167346981Scy#ifdef CONFIG_IEEE80211R_AP 2168346981Scy } else if (wpa_key_mgmt_ft(sm->wpa_key_mgmt) && 2169346981Scy sm->ft_completed) { 2170346981Scy wpa_printf(MSG_DEBUG, 2171346981Scy "FT: No PMKID in message 1/4 when using FT protocol"); 2172346981Scy pmkid = NULL; 2173346981Scy pmkid_len = 0; 2174346981Scy#endif /* CONFIG_IEEE80211R_AP */ 2175346981Scy#ifdef CONFIG_SAE 2176346981Scy } else if (wpa_key_mgmt_sae(sm->wpa_key_mgmt)) { 2177346981Scy if (sm->pmkid_set) { 2178346981Scy wpa_hexdump(MSG_DEBUG, 2179346981Scy "RSN: Message 1/4 PMKID from SAE", 2180346981Scy sm->pmkid, PMKID_LEN); 2181346981Scy os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN], 2182346981Scy sm->pmkid, PMKID_LEN); 2183346981Scy } else { 2184346981Scy /* No PMKID available */ 2185346981Scy wpa_printf(MSG_DEBUG, 2186346981Scy "RSN: No SAE PMKID available for message 1/4"); 2187346981Scy pmkid = NULL; 2188346981Scy } 2189346981Scy#endif /* CONFIG_SAE */ 2190281806Srpaulo } else { 2191214501Srpaulo /* 2192214501Srpaulo * Calculate PMKID since no PMKSA cache entry was 2193214501Srpaulo * available with pre-calculated PMKID. 2194214501Srpaulo */ 2195337817Scy rsn_pmkid(sm->PMK, sm->pmk_len, sm->wpa_auth->addr, 2196214501Srpaulo sm->addr, &pmkid[2 + RSN_SELECTOR_LEN], 2197346981Scy sm->wpa_key_mgmt); 2198346981Scy wpa_hexdump(MSG_DEBUG, 2199346981Scy "RSN: Message 1/4 PMKID derived from PMK", 2200346981Scy &pmkid[2 + RSN_SELECTOR_LEN], PMKID_LEN); 2201214501Srpaulo } 2202214501Srpaulo } 2203214501Srpaulo wpa_send_eapol(sm->wpa_auth, sm, 2204214501Srpaulo WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL, 2205214501Srpaulo sm->ANonce, pmkid, pmkid_len, 0, 0); 2206214501Srpaulo} 2207214501Srpaulo 2208214501Srpaulo 2209281806Srpaulostatic int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce, 2210337817Scy const u8 *pmk, unsigned int pmk_len, 2211337817Scy struct wpa_ptk *ptk) 2212214501Srpaulo{ 2213346981Scy const u8 *z = NULL; 2214346981Scy size_t z_len = 0; 2215214501Srpaulo 2216346981Scy#ifdef CONFIG_IEEE80211R_AP 2217346981Scy if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { 2218346981Scy if (sm->ft_completed) { 2219346981Scy u8 ptk_name[WPA_PMK_NAME_LEN]; 2220346981Scy 2221346981Scy return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len, 2222346981Scy sm->SNonce, sm->ANonce, 2223346981Scy sm->addr, sm->wpa_auth->addr, 2224346981Scy sm->pmk_r1_name, 2225346981Scy ptk, ptk_name, 2226346981Scy sm->wpa_key_mgmt, 2227346981Scy sm->pairwise); 2228346981Scy } 2229346981Scy return wpa_auth_derive_ptk_ft(sm, ptk); 2230346981Scy } 2231346981Scy#endif /* CONFIG_IEEE80211R_AP */ 2232346981Scy 2233346981Scy#ifdef CONFIG_DPP2 2234346981Scy if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->dpp_z) { 2235346981Scy z = wpabuf_head(sm->dpp_z); 2236346981Scy z_len = wpabuf_len(sm->dpp_z); 2237346981Scy } 2238346981Scy#endif /* CONFIG_DPP2 */ 2239346981Scy 2240337817Scy return wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion", 2241281806Srpaulo sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce, 2242346981Scy ptk, sm->wpa_key_mgmt, sm->pairwise, z, z_len); 2243214501Srpaulo} 2244214501Srpaulo 2245214501Srpaulo 2246346981Scy#ifdef CONFIG_FILS 2247346981Scy 2248346981Scyint fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk, 2249346981Scy size_t pmk_len, const u8 *snonce, const u8 *anonce, 2250346981Scy const u8 *dhss, size_t dhss_len, 2251346981Scy struct wpabuf *g_sta, struct wpabuf *g_ap) 2252346981Scy{ 2253346981Scy u8 ick[FILS_ICK_MAX_LEN]; 2254346981Scy size_t ick_len; 2255346981Scy int res; 2256346981Scy u8 fils_ft[FILS_FT_MAX_LEN]; 2257346981Scy size_t fils_ft_len = 0; 2258346981Scy 2259346981Scy res = fils_pmk_to_ptk(pmk, pmk_len, sm->addr, sm->wpa_auth->addr, 2260346981Scy snonce, anonce, dhss, dhss_len, 2261346981Scy &sm->PTK, ick, &ick_len, 2262346981Scy sm->wpa_key_mgmt, sm->pairwise, 2263346981Scy fils_ft, &fils_ft_len); 2264346981Scy if (res < 0) 2265346981Scy return res; 2266346981Scy sm->PTK_valid = TRUE; 2267346981Scy sm->tk_already_set = FALSE; 2268346981Scy 2269346981Scy#ifdef CONFIG_IEEE80211R_AP 2270346981Scy if (fils_ft_len) { 2271346981Scy struct wpa_authenticator *wpa_auth = sm->wpa_auth; 2272346981Scy struct wpa_auth_config *conf = &wpa_auth->conf; 2273346981Scy u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN]; 2274346981Scy int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt); 2275346981Scy size_t pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN; 2276346981Scy 2277346981Scy if (wpa_derive_pmk_r0(fils_ft, fils_ft_len, 2278346981Scy conf->ssid, conf->ssid_len, 2279346981Scy conf->mobility_domain, 2280346981Scy conf->r0_key_holder, 2281346981Scy conf->r0_key_holder_len, 2282346981Scy sm->addr, pmk_r0, pmk_r0_name, 2283346981Scy use_sha384) < 0) 2284346981Scy return -1; 2285346981Scy 2286346981Scy wpa_hexdump_key(MSG_DEBUG, "FILS+FT: PMK-R0", 2287346981Scy pmk_r0, pmk_r0_len); 2288346981Scy wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR0Name", 2289346981Scy pmk_r0_name, WPA_PMK_NAME_LEN); 2290346981Scy wpa_ft_store_pmk_fils(sm, pmk_r0, pmk_r0_name); 2291351611Scy forced_memzero(fils_ft, sizeof(fils_ft)); 2292346981Scy 2293346981Scy res = wpa_derive_pmk_r1_name(pmk_r0_name, conf->r1_key_holder, 2294346981Scy sm->addr, sm->pmk_r1_name, 2295346981Scy use_sha384); 2296351611Scy forced_memzero(pmk_r0, PMK_LEN_MAX); 2297346981Scy if (res < 0) 2298346981Scy return -1; 2299346981Scy wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR1Name", sm->pmk_r1_name, 2300346981Scy WPA_PMK_NAME_LEN); 2301346981Scy sm->pmk_r1_name_valid = 1; 2302346981Scy } 2303346981Scy#endif /* CONFIG_IEEE80211R_AP */ 2304346981Scy 2305346981Scy res = fils_key_auth_sk(ick, ick_len, snonce, anonce, 2306346981Scy sm->addr, sm->wpa_auth->addr, 2307346981Scy g_sta ? wpabuf_head(g_sta) : NULL, 2308346981Scy g_sta ? wpabuf_len(g_sta) : 0, 2309346981Scy g_ap ? wpabuf_head(g_ap) : NULL, 2310346981Scy g_ap ? wpabuf_len(g_ap) : 0, 2311346981Scy sm->wpa_key_mgmt, sm->fils_key_auth_sta, 2312346981Scy sm->fils_key_auth_ap, 2313346981Scy &sm->fils_key_auth_len); 2314351611Scy forced_memzero(ick, sizeof(ick)); 2315346981Scy 2316346981Scy /* Store nonces for (Re)Association Request/Response frame processing */ 2317346981Scy os_memcpy(sm->SNonce, snonce, FILS_NONCE_LEN); 2318346981Scy os_memcpy(sm->ANonce, anonce, FILS_NONCE_LEN); 2319346981Scy 2320346981Scy return res; 2321346981Scy} 2322346981Scy 2323346981Scy 2324346981Scystatic int wpa_aead_decrypt(struct wpa_state_machine *sm, struct wpa_ptk *ptk, 2325346981Scy u8 *buf, size_t buf_len, u16 *_key_data_len) 2326346981Scy{ 2327346981Scy struct ieee802_1x_hdr *hdr; 2328346981Scy struct wpa_eapol_key *key; 2329346981Scy u8 *pos; 2330346981Scy u16 key_data_len; 2331346981Scy u8 *tmp; 2332346981Scy const u8 *aad[1]; 2333346981Scy size_t aad_len[1]; 2334346981Scy 2335346981Scy hdr = (struct ieee802_1x_hdr *) buf; 2336346981Scy key = (struct wpa_eapol_key *) (hdr + 1); 2337346981Scy pos = (u8 *) (key + 1); 2338346981Scy key_data_len = WPA_GET_BE16(pos); 2339346981Scy if (key_data_len < AES_BLOCK_SIZE || 2340346981Scy key_data_len > buf_len - sizeof(*hdr) - sizeof(*key) - 2) { 2341346981Scy wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, 2342346981Scy "No room for AES-SIV data in the frame"); 2343346981Scy return -1; 2344346981Scy } 2345346981Scy pos += 2; /* Pointing at the Encrypted Key Data field */ 2346346981Scy 2347346981Scy tmp = os_malloc(key_data_len); 2348346981Scy if (!tmp) 2349346981Scy return -1; 2350346981Scy 2351346981Scy /* AES-SIV AAD from EAPOL protocol version field (inclusive) to 2352346981Scy * to Key Data (exclusive). */ 2353346981Scy aad[0] = buf; 2354346981Scy aad_len[0] = pos - buf; 2355346981Scy if (aes_siv_decrypt(ptk->kek, ptk->kek_len, pos, key_data_len, 2356346981Scy 1, aad, aad_len, tmp) < 0) { 2357346981Scy wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, 2358346981Scy "Invalid AES-SIV data in the frame"); 2359346981Scy bin_clear_free(tmp, key_data_len); 2360346981Scy return -1; 2361346981Scy } 2362346981Scy 2363346981Scy /* AEAD decryption and validation completed successfully */ 2364346981Scy key_data_len -= AES_BLOCK_SIZE; 2365346981Scy wpa_hexdump_key(MSG_DEBUG, "WPA: Decrypted Key Data", 2366346981Scy tmp, key_data_len); 2367346981Scy 2368346981Scy /* Replace Key Data field with the decrypted version */ 2369346981Scy os_memcpy(pos, tmp, key_data_len); 2370346981Scy pos -= 2; /* Key Data Length field */ 2371346981Scy WPA_PUT_BE16(pos, key_data_len); 2372346981Scy bin_clear_free(tmp, key_data_len); 2373346981Scy if (_key_data_len) 2374346981Scy *_key_data_len = key_data_len; 2375346981Scy return 0; 2376346981Scy} 2377346981Scy 2378346981Scy 2379346981Scyconst u8 * wpa_fils_validate_fils_session(struct wpa_state_machine *sm, 2380346981Scy const u8 *ies, size_t ies_len, 2381346981Scy const u8 *fils_session) 2382346981Scy{ 2383346981Scy const u8 *ie, *end; 2384346981Scy const u8 *session = NULL; 2385346981Scy 2386346981Scy if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt)) { 2387346981Scy wpa_printf(MSG_DEBUG, 2388346981Scy "FILS: Not a FILS AKM - reject association"); 2389346981Scy return NULL; 2390346981Scy } 2391346981Scy 2392346981Scy /* Verify Session element */ 2393346981Scy ie = ies; 2394346981Scy end = ((const u8 *) ie) + ies_len; 2395346981Scy while (ie + 1 < end) { 2396346981Scy if (ie + 2 + ie[1] > end) 2397346981Scy break; 2398346981Scy if (ie[0] == WLAN_EID_EXTENSION && 2399346981Scy ie[1] >= 1 + FILS_SESSION_LEN && 2400346981Scy ie[2] == WLAN_EID_EXT_FILS_SESSION) { 2401346981Scy session = ie; 2402346981Scy break; 2403346981Scy } 2404346981Scy ie += 2 + ie[1]; 2405346981Scy } 2406346981Scy 2407346981Scy if (!session) { 2408346981Scy wpa_printf(MSG_DEBUG, 2409346981Scy "FILS: %s: Could not find FILS Session element in Assoc Req - reject", 2410346981Scy __func__); 2411346981Scy return NULL; 2412346981Scy } 2413346981Scy 2414346981Scy if (!fils_session) { 2415346981Scy wpa_printf(MSG_DEBUG, 2416346981Scy "FILS: %s: Could not find FILS Session element in STA entry - reject", 2417346981Scy __func__); 2418346981Scy return NULL; 2419346981Scy } 2420346981Scy 2421346981Scy if (os_memcmp(fils_session, session + 3, FILS_SESSION_LEN) != 0) { 2422346981Scy wpa_printf(MSG_DEBUG, "FILS: Session mismatch"); 2423346981Scy wpa_hexdump(MSG_DEBUG, "FILS: Expected FILS Session", 2424346981Scy fils_session, FILS_SESSION_LEN); 2425346981Scy wpa_hexdump(MSG_DEBUG, "FILS: Received FILS Session", 2426346981Scy session + 3, FILS_SESSION_LEN); 2427346981Scy return NULL; 2428346981Scy } 2429346981Scy return session; 2430346981Scy} 2431346981Scy 2432346981Scy 2433346981Scyint wpa_fils_validate_key_confirm(struct wpa_state_machine *sm, const u8 *ies, 2434346981Scy size_t ies_len) 2435346981Scy{ 2436346981Scy struct ieee802_11_elems elems; 2437346981Scy 2438346981Scy if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) { 2439346981Scy wpa_printf(MSG_DEBUG, 2440346981Scy "FILS: Failed to parse decrypted elements"); 2441346981Scy return -1; 2442346981Scy } 2443346981Scy 2444346981Scy if (!elems.fils_session) { 2445346981Scy wpa_printf(MSG_DEBUG, "FILS: No FILS Session element"); 2446346981Scy return -1; 2447346981Scy } 2448346981Scy 2449346981Scy if (!elems.fils_key_confirm) { 2450346981Scy wpa_printf(MSG_DEBUG, "FILS: No FILS Key Confirm element"); 2451346981Scy return -1; 2452346981Scy } 2453346981Scy 2454346981Scy if (elems.fils_key_confirm_len != sm->fils_key_auth_len) { 2455346981Scy wpa_printf(MSG_DEBUG, 2456346981Scy "FILS: Unexpected Key-Auth length %d (expected %d)", 2457346981Scy elems.fils_key_confirm_len, 2458346981Scy (int) sm->fils_key_auth_len); 2459346981Scy return -1; 2460346981Scy } 2461346981Scy 2462346981Scy if (os_memcmp(elems.fils_key_confirm, sm->fils_key_auth_sta, 2463346981Scy sm->fils_key_auth_len) != 0) { 2464346981Scy wpa_printf(MSG_DEBUG, "FILS: Key-Auth mismatch"); 2465346981Scy wpa_hexdump(MSG_DEBUG, "FILS: Received Key-Auth", 2466346981Scy elems.fils_key_confirm, elems.fils_key_confirm_len); 2467346981Scy wpa_hexdump(MSG_DEBUG, "FILS: Expected Key-Auth", 2468346981Scy sm->fils_key_auth_sta, sm->fils_key_auth_len); 2469346981Scy return -1; 2470346981Scy } 2471346981Scy 2472346981Scy return 0; 2473346981Scy} 2474346981Scy 2475346981Scy 2476346981Scyint fils_decrypt_assoc(struct wpa_state_machine *sm, const u8 *fils_session, 2477346981Scy const struct ieee80211_mgmt *mgmt, size_t frame_len, 2478346981Scy u8 *pos, size_t left) 2479346981Scy{ 2480346981Scy u16 fc, stype; 2481346981Scy const u8 *end, *ie_start, *ie, *session, *crypt; 2482346981Scy const u8 *aad[5]; 2483346981Scy size_t aad_len[5]; 2484346981Scy 2485346981Scy if (!sm || !sm->PTK_valid) { 2486346981Scy wpa_printf(MSG_DEBUG, 2487346981Scy "FILS: No KEK to decrypt Assocication Request frame"); 2488346981Scy return -1; 2489346981Scy } 2490346981Scy 2491346981Scy if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt)) { 2492346981Scy wpa_printf(MSG_DEBUG, 2493346981Scy "FILS: Not a FILS AKM - reject association"); 2494346981Scy return -1; 2495346981Scy } 2496346981Scy 2497346981Scy end = ((const u8 *) mgmt) + frame_len; 2498346981Scy fc = le_to_host16(mgmt->frame_control); 2499346981Scy stype = WLAN_FC_GET_STYPE(fc); 2500346981Scy if (stype == WLAN_FC_STYPE_REASSOC_REQ) 2501346981Scy ie_start = mgmt->u.reassoc_req.variable; 2502346981Scy else 2503346981Scy ie_start = mgmt->u.assoc_req.variable; 2504346981Scy ie = ie_start; 2505346981Scy 2506346981Scy /* 2507346981Scy * Find FILS Session element which is the last unencrypted element in 2508346981Scy * the frame. 2509346981Scy */ 2510346981Scy session = wpa_fils_validate_fils_session(sm, ie, end - ie, 2511346981Scy fils_session); 2512346981Scy if (!session) { 2513346981Scy wpa_printf(MSG_DEBUG, "FILS: Session validation failed"); 2514346981Scy return -1; 2515346981Scy } 2516346981Scy 2517346981Scy crypt = session + 2 + session[1]; 2518346981Scy 2519346981Scy if (end - crypt < AES_BLOCK_SIZE) { 2520346981Scy wpa_printf(MSG_DEBUG, 2521346981Scy "FILS: Too short frame to include AES-SIV data"); 2522346981Scy return -1; 2523346981Scy } 2524346981Scy 2525346981Scy /* AES-SIV AAD vectors */ 2526346981Scy 2527346981Scy /* The STA's MAC address */ 2528346981Scy aad[0] = mgmt->sa; 2529346981Scy aad_len[0] = ETH_ALEN; 2530346981Scy /* The AP's BSSID */ 2531346981Scy aad[1] = mgmt->da; 2532346981Scy aad_len[1] = ETH_ALEN; 2533346981Scy /* The STA's nonce */ 2534346981Scy aad[2] = sm->SNonce; 2535346981Scy aad_len[2] = FILS_NONCE_LEN; 2536346981Scy /* The AP's nonce */ 2537346981Scy aad[3] = sm->ANonce; 2538346981Scy aad_len[3] = FILS_NONCE_LEN; 2539346981Scy /* 2540346981Scy * The (Re)Association Request frame from the Capability Information 2541346981Scy * field to the FILS Session element (both inclusive). 2542346981Scy */ 2543346981Scy aad[4] = (const u8 *) &mgmt->u.assoc_req.capab_info; 2544346981Scy aad_len[4] = crypt - aad[4]; 2545346981Scy 2546346981Scy if (aes_siv_decrypt(sm->PTK.kek, sm->PTK.kek_len, crypt, end - crypt, 2547346981Scy 5, aad, aad_len, pos + (crypt - ie_start)) < 0) { 2548346981Scy wpa_printf(MSG_DEBUG, 2549346981Scy "FILS: Invalid AES-SIV data in the frame"); 2550346981Scy return -1; 2551346981Scy } 2552346981Scy wpa_hexdump(MSG_DEBUG, "FILS: Decrypted Association Request elements", 2553346981Scy pos, left - AES_BLOCK_SIZE); 2554346981Scy 2555346981Scy if (wpa_fils_validate_key_confirm(sm, pos, left - AES_BLOCK_SIZE) < 0) { 2556346981Scy wpa_printf(MSG_DEBUG, "FILS: Key Confirm validation failed"); 2557346981Scy return -1; 2558346981Scy } 2559346981Scy 2560346981Scy return left - AES_BLOCK_SIZE; 2561346981Scy} 2562346981Scy 2563346981Scy 2564346981Scyint fils_encrypt_assoc(struct wpa_state_machine *sm, u8 *buf, 2565346981Scy size_t current_len, size_t max_len, 2566346981Scy const struct wpabuf *hlp) 2567346981Scy{ 2568346981Scy u8 *end = buf + max_len; 2569346981Scy u8 *pos = buf + current_len; 2570346981Scy struct ieee80211_mgmt *mgmt; 2571346981Scy struct wpabuf *plain; 2572346981Scy const u8 *aad[5]; 2573346981Scy size_t aad_len[5]; 2574346981Scy 2575346981Scy if (!sm || !sm->PTK_valid) 2576346981Scy return -1; 2577346981Scy 2578346981Scy wpa_hexdump(MSG_DEBUG, 2579346981Scy "FILS: Association Response frame before FILS processing", 2580346981Scy buf, current_len); 2581346981Scy 2582346981Scy mgmt = (struct ieee80211_mgmt *) buf; 2583346981Scy 2584346981Scy /* AES-SIV AAD vectors */ 2585346981Scy 2586346981Scy /* The AP's BSSID */ 2587346981Scy aad[0] = mgmt->sa; 2588346981Scy aad_len[0] = ETH_ALEN; 2589346981Scy /* The STA's MAC address */ 2590346981Scy aad[1] = mgmt->da; 2591346981Scy aad_len[1] = ETH_ALEN; 2592346981Scy /* The AP's nonce */ 2593346981Scy aad[2] = sm->ANonce; 2594346981Scy aad_len[2] = FILS_NONCE_LEN; 2595346981Scy /* The STA's nonce */ 2596346981Scy aad[3] = sm->SNonce; 2597346981Scy aad_len[3] = FILS_NONCE_LEN; 2598346981Scy /* 2599346981Scy * The (Re)Association Response frame from the Capability Information 2600346981Scy * field (the same offset in both Association and Reassociation 2601346981Scy * Response frames) to the FILS Session element (both inclusive). 2602346981Scy */ 2603346981Scy aad[4] = (const u8 *) &mgmt->u.assoc_resp.capab_info; 2604346981Scy aad_len[4] = pos - aad[4]; 2605346981Scy 2606346981Scy /* The following elements will be encrypted with AES-SIV */ 2607346981Scy plain = fils_prepare_plainbuf(sm, hlp); 2608346981Scy if (!plain) { 2609346981Scy wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed"); 2610346981Scy return -1; 2611346981Scy } 2612346981Scy 2613346981Scy if (pos + wpabuf_len(plain) + AES_BLOCK_SIZE > end) { 2614346981Scy wpa_printf(MSG_DEBUG, 2615346981Scy "FILS: Not enough room for FILS elements"); 2616351611Scy wpabuf_clear_free(plain); 2617346981Scy return -1; 2618346981Scy } 2619346981Scy 2620346981Scy wpa_hexdump_buf_key(MSG_DEBUG, "FILS: Association Response plaintext", 2621346981Scy plain); 2622346981Scy 2623346981Scy if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len, 2624346981Scy wpabuf_head(plain), wpabuf_len(plain), 2625346981Scy 5, aad, aad_len, pos) < 0) { 2626351611Scy wpabuf_clear_free(plain); 2627346981Scy return -1; 2628346981Scy } 2629346981Scy 2630346981Scy wpa_hexdump(MSG_DEBUG, 2631346981Scy "FILS: Encrypted Association Response elements", 2632346981Scy pos, AES_BLOCK_SIZE + wpabuf_len(plain)); 2633346981Scy current_len += wpabuf_len(plain) + AES_BLOCK_SIZE; 2634351611Scy wpabuf_clear_free(plain); 2635346981Scy 2636346981Scy sm->fils_completed = 1; 2637346981Scy 2638346981Scy return current_len; 2639346981Scy} 2640346981Scy 2641346981Scy 2642346981Scystatic struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm, 2643346981Scy const struct wpabuf *hlp) 2644346981Scy{ 2645346981Scy struct wpabuf *plain; 2646346981Scy u8 *len, *tmp, *tmp2; 2647346981Scy u8 hdr[2]; 2648346981Scy u8 *gtk, dummy_gtk[32]; 2649346981Scy size_t gtk_len; 2650346981Scy struct wpa_group *gsm; 2651346981Scy 2652346981Scy plain = wpabuf_alloc(1000); 2653346981Scy if (!plain) 2654346981Scy return NULL; 2655346981Scy 2656346981Scy /* TODO: FILS Public Key */ 2657346981Scy 2658346981Scy /* FILS Key Confirmation */ 2659346981Scy wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */ 2660346981Scy wpabuf_put_u8(plain, 1 + sm->fils_key_auth_len); /* Length */ 2661346981Scy /* Element ID Extension */ 2662346981Scy wpabuf_put_u8(plain, WLAN_EID_EXT_FILS_KEY_CONFIRM); 2663346981Scy wpabuf_put_data(plain, sm->fils_key_auth_ap, sm->fils_key_auth_len); 2664346981Scy 2665346981Scy /* FILS HLP Container */ 2666346981Scy if (hlp) 2667346981Scy wpabuf_put_buf(plain, hlp); 2668346981Scy 2669346981Scy /* TODO: FILS IP Address Assignment */ 2670346981Scy 2671346981Scy /* Key Delivery */ 2672346981Scy gsm = sm->group; 2673346981Scy wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */ 2674346981Scy len = wpabuf_put(plain, 1); 2675346981Scy wpabuf_put_u8(plain, WLAN_EID_EXT_KEY_DELIVERY); 2676346981Scy wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, 2677346981Scy wpabuf_put(plain, WPA_KEY_RSC_LEN)); 2678346981Scy /* GTK KDE */ 2679346981Scy gtk = gsm->GTK[gsm->GN - 1]; 2680346981Scy gtk_len = gsm->GTK_len; 2681346981Scy if (sm->wpa_auth->conf.disable_gtk || 2682346981Scy sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { 2683346981Scy /* 2684346981Scy * Provide unique random GTK to each STA to prevent use 2685346981Scy * of GTK in the BSS. 2686346981Scy */ 2687346981Scy if (random_get_bytes(dummy_gtk, gtk_len) < 0) { 2688351611Scy wpabuf_clear_free(plain); 2689346981Scy return NULL; 2690346981Scy } 2691346981Scy gtk = dummy_gtk; 2692346981Scy } 2693346981Scy hdr[0] = gsm->GN & 0x03; 2694346981Scy hdr[1] = 0; 2695346981Scy tmp = wpabuf_put(plain, 0); 2696346981Scy tmp2 = wpa_add_kde(tmp, RSN_KEY_DATA_GROUPKEY, hdr, 2, 2697346981Scy gtk, gtk_len); 2698346981Scy wpabuf_put(plain, tmp2 - tmp); 2699346981Scy 2700346981Scy /* IGTK KDE */ 2701346981Scy tmp = wpabuf_put(plain, 0); 2702346981Scy tmp2 = ieee80211w_kde_add(sm, tmp); 2703346981Scy wpabuf_put(plain, tmp2 - tmp); 2704346981Scy 2705346981Scy *len = (u8 *) wpabuf_put(plain, 0) - len - 1; 2706346981Scy 2707346981Scy#ifdef CONFIG_OCV 2708346981Scy if (wpa_auth_uses_ocv(sm)) { 2709346981Scy struct wpa_channel_info ci; 2710346981Scy u8 *pos; 2711346981Scy 2712346981Scy if (wpa_channel_info(sm->wpa_auth, &ci) != 0) { 2713346981Scy wpa_printf(MSG_WARNING, 2714346981Scy "FILS: Failed to get channel info for OCI element"); 2715351611Scy wpabuf_clear_free(plain); 2716346981Scy return NULL; 2717346981Scy } 2718346981Scy 2719346981Scy pos = wpabuf_put(plain, OCV_OCI_EXTENDED_LEN); 2720346981Scy if (ocv_insert_extended_oci(&ci, pos) < 0) { 2721351611Scy wpabuf_clear_free(plain); 2722346981Scy return NULL; 2723346981Scy } 2724346981Scy } 2725346981Scy#endif /* CONFIG_OCV */ 2726346981Scy 2727346981Scy return plain; 2728346981Scy} 2729346981Scy 2730346981Scy 2731346981Scyint fils_set_tk(struct wpa_state_machine *sm) 2732346981Scy{ 2733346981Scy enum wpa_alg alg; 2734346981Scy int klen; 2735346981Scy 2736346981Scy if (!sm || !sm->PTK_valid) { 2737346981Scy wpa_printf(MSG_DEBUG, "FILS: No valid PTK available to set TK"); 2738346981Scy return -1; 2739346981Scy } 2740346981Scy if (sm->tk_already_set) { 2741346981Scy wpa_printf(MSG_DEBUG, "FILS: TK already set to the driver"); 2742346981Scy return -1; 2743346981Scy } 2744346981Scy 2745346981Scy alg = wpa_cipher_to_alg(sm->pairwise); 2746346981Scy klen = wpa_cipher_key_len(sm->pairwise); 2747346981Scy 2748346981Scy wpa_printf(MSG_DEBUG, "FILS: Configure TK to the driver"); 2749346981Scy if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, 2750346981Scy sm->PTK.tk, klen)) { 2751346981Scy wpa_printf(MSG_DEBUG, "FILS: Failed to set TK to the driver"); 2752346981Scy return -1; 2753346981Scy } 2754346981Scy sm->tk_already_set = TRUE; 2755346981Scy 2756346981Scy return 0; 2757346981Scy} 2758346981Scy 2759346981Scy 2760346981Scyu8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *buf, 2761346981Scy const u8 *fils_session, struct wpabuf *hlp) 2762346981Scy{ 2763346981Scy struct wpabuf *plain; 2764346981Scy u8 *pos = buf; 2765346981Scy 2766346981Scy /* FILS Session */ 2767346981Scy *pos++ = WLAN_EID_EXTENSION; /* Element ID */ 2768346981Scy *pos++ = 1 + FILS_SESSION_LEN; /* Length */ 2769346981Scy *pos++ = WLAN_EID_EXT_FILS_SESSION; /* Element ID Extension */ 2770346981Scy os_memcpy(pos, fils_session, FILS_SESSION_LEN); 2771346981Scy pos += FILS_SESSION_LEN; 2772346981Scy 2773346981Scy plain = fils_prepare_plainbuf(sm, hlp); 2774346981Scy if (!plain) { 2775346981Scy wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed"); 2776346981Scy return NULL; 2777346981Scy } 2778346981Scy 2779346981Scy os_memcpy(pos, wpabuf_head(plain), wpabuf_len(plain)); 2780346981Scy pos += wpabuf_len(plain); 2781346981Scy 2782346981Scy wpa_printf(MSG_DEBUG, "%s: plain buf_len: %u", __func__, 2783346981Scy (unsigned int) wpabuf_len(plain)); 2784351611Scy wpabuf_clear_free(plain); 2785346981Scy sm->fils_completed = 1; 2786346981Scy return pos; 2787346981Scy} 2788346981Scy 2789346981Scy#endif /* CONFIG_FILS */ 2790346981Scy 2791346981Scy 2792346981Scy#ifdef CONFIG_OCV 2793346981Scyint get_sta_tx_parameters(struct wpa_state_machine *sm, int ap_max_chanwidth, 2794346981Scy int ap_seg1_idx, int *bandwidth, int *seg1_idx) 2795346981Scy{ 2796346981Scy struct wpa_authenticator *wpa_auth = sm->wpa_auth; 2797346981Scy 2798346981Scy if (!wpa_auth->cb->get_sta_tx_params) 2799346981Scy return -1; 2800346981Scy return wpa_auth->cb->get_sta_tx_params(wpa_auth->cb_ctx, sm->addr, 2801346981Scy ap_max_chanwidth, ap_seg1_idx, 2802346981Scy bandwidth, seg1_idx); 2803346981Scy} 2804346981Scy#endif /* CONFIG_OCV */ 2805346981Scy 2806346981Scy 2807214501SrpauloSM_STATE(WPA_PTK, PTKCALCNEGOTIATING) 2808214501Srpaulo{ 2809346981Scy struct wpa_authenticator *wpa_auth = sm->wpa_auth; 2810214501Srpaulo struct wpa_ptk PTK; 2811289549Srpaulo int ok = 0, psk_found = 0; 2812214501Srpaulo const u8 *pmk = NULL; 2813346981Scy size_t pmk_len; 2814346981Scy int ft; 2815346981Scy const u8 *eapol_key_ie, *key_data, *mic; 2816346981Scy u16 key_data_length; 2817346981Scy size_t mic_len, eapol_key_ie_len; 2818346981Scy struct ieee802_1x_hdr *hdr; 2819346981Scy struct wpa_eapol_key *key; 2820346981Scy struct wpa_eapol_ie_parse kde; 2821346981Scy int vlan_id = 0; 2822214501Srpaulo 2823214501Srpaulo SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk); 2824214501Srpaulo sm->EAPOLKeyReceived = FALSE; 2825252726Srpaulo sm->update_snonce = FALSE; 2826346981Scy os_memset(&PTK, 0, sizeof(PTK)); 2827214501Srpaulo 2828346981Scy mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len); 2829346981Scy 2830214501Srpaulo /* WPA with IEEE 802.1X: use the derived PMK from EAP 2831214501Srpaulo * WPA-PSK: iterate through possible PSKs and select the one matching 2832214501Srpaulo * the packet */ 2833214501Srpaulo for (;;) { 2834346981Scy if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) && 2835346981Scy !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) { 2836281806Srpaulo pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, 2837346981Scy sm->p2p_dev_addr, pmk, &pmk_len, 2838346981Scy &vlan_id); 2839214501Srpaulo if (pmk == NULL) 2840214501Srpaulo break; 2841289549Srpaulo psk_found = 1; 2842346981Scy#ifdef CONFIG_IEEE80211R_AP 2843346981Scy if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) { 2844346981Scy os_memcpy(sm->xxkey, pmk, pmk_len); 2845346981Scy sm->xxkey_len = pmk_len; 2846346981Scy } 2847346981Scy#endif /* CONFIG_IEEE80211R_AP */ 2848337817Scy } else { 2849214501Srpaulo pmk = sm->PMK; 2850337817Scy pmk_len = sm->pmk_len; 2851337817Scy } 2852214501Srpaulo 2853346981Scy if ((!pmk || !pmk_len) && sm->pmksa) { 2854346981Scy wpa_printf(MSG_DEBUG, "WPA: Use PMK from PMKSA cache"); 2855346981Scy pmk = sm->pmksa->pmk; 2856346981Scy pmk_len = sm->pmksa->pmk_len; 2857346981Scy } 2858214501Srpaulo 2859346981Scy if (wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK) < 0) 2860346981Scy break; 2861346981Scy 2862346981Scy if (mic_len && 2863346981Scy wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK, 2864281806Srpaulo sm->last_rx_eapol_key, 2865214501Srpaulo sm->last_rx_eapol_key_len) == 0) { 2866346981Scy if (sm->PMK != pmk) { 2867346981Scy os_memcpy(sm->PMK, pmk, pmk_len); 2868346981Scy sm->pmk_len = pmk_len; 2869346981Scy } 2870214501Srpaulo ok = 1; 2871214501Srpaulo break; 2872214501Srpaulo } 2873214501Srpaulo 2874346981Scy#ifdef CONFIG_FILS 2875346981Scy if (!mic_len && 2876346981Scy wpa_aead_decrypt(sm, &PTK, sm->last_rx_eapol_key, 2877346981Scy sm->last_rx_eapol_key_len, NULL) == 0) { 2878346981Scy ok = 1; 2879214501Srpaulo break; 2880346981Scy } 2881346981Scy#endif /* CONFIG_FILS */ 2882346981Scy 2883346981Scy if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) || 2884346981Scy wpa_key_mgmt_sae(sm->wpa_key_mgmt)) 2885346981Scy break; 2886214501Srpaulo } 2887214501Srpaulo 2888214501Srpaulo if (!ok) { 2889214501Srpaulo wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 2890214501Srpaulo "invalid MIC in msg 2/4 of 4-Way Handshake"); 2891289549Srpaulo if (psk_found) 2892289549Srpaulo wpa_auth_psk_failure_report(sm->wpa_auth, sm->addr); 2893214501Srpaulo return; 2894214501Srpaulo } 2895214501Srpaulo 2896346981Scy /* 2897346981Scy * Note: last_rx_eapol_key length fields have already been validated in 2898346981Scy * wpa_receive(). 2899346981Scy */ 2900346981Scy hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key; 2901346981Scy key = (struct wpa_eapol_key *) (hdr + 1); 2902346981Scy mic = (u8 *) (key + 1); 2903346981Scy key_data = mic + mic_len + 2; 2904346981Scy key_data_length = WPA_GET_BE16(mic + mic_len); 2905346981Scy if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) - 2906346981Scy sizeof(*key) - mic_len - 2) 2907346981Scy return; 2908346981Scy 2909346981Scy if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) { 2910346981Scy wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, 2911346981Scy "received EAPOL-Key msg 2/4 with invalid Key Data contents"); 2912346981Scy return; 2913346981Scy } 2914346981Scy if (kde.rsn_ie) { 2915346981Scy eapol_key_ie = kde.rsn_ie; 2916346981Scy eapol_key_ie_len = kde.rsn_ie_len; 2917346981Scy } else if (kde.osen) { 2918346981Scy eapol_key_ie = kde.osen; 2919346981Scy eapol_key_ie_len = kde.osen_len; 2920346981Scy } else { 2921346981Scy eapol_key_ie = kde.wpa_ie; 2922346981Scy eapol_key_ie_len = kde.wpa_ie_len; 2923346981Scy } 2924346981Scy ft = sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt); 2925346981Scy if (sm->wpa_ie == NULL || 2926346981Scy wpa_compare_rsn_ie(ft, sm->wpa_ie, sm->wpa_ie_len, 2927346981Scy eapol_key_ie, eapol_key_ie_len)) { 2928346981Scy wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 2929346981Scy "WPA IE from (Re)AssocReq did not match with msg 2/4"); 2930346981Scy if (sm->wpa_ie) { 2931346981Scy wpa_hexdump(MSG_DEBUG, "WPA IE in AssocReq", 2932346981Scy sm->wpa_ie, sm->wpa_ie_len); 2933346981Scy } 2934346981Scy wpa_hexdump(MSG_DEBUG, "WPA IE in msg 2/4", 2935346981Scy eapol_key_ie, eapol_key_ie_len); 2936346981Scy /* MLME-DEAUTHENTICATE.request */ 2937346981Scy wpa_sta_disconnect(wpa_auth, sm->addr, 2938346981Scy WLAN_REASON_PREV_AUTH_NOT_VALID); 2939346981Scy return; 2940346981Scy } 2941346981Scy#ifdef CONFIG_OCV 2942346981Scy if (wpa_auth_uses_ocv(sm)) { 2943346981Scy struct wpa_channel_info ci; 2944346981Scy int tx_chanwidth; 2945346981Scy int tx_seg1_idx; 2946346981Scy 2947346981Scy if (wpa_channel_info(wpa_auth, &ci) != 0) { 2948346981Scy wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 2949346981Scy "Failed to get channel info to validate received OCI in EAPOL-Key 2/4"); 2950346981Scy return; 2951346981Scy } 2952346981Scy 2953346981Scy if (get_sta_tx_parameters(sm, 2954346981Scy channel_width_to_int(ci.chanwidth), 2955346981Scy ci.seg1_idx, &tx_chanwidth, 2956346981Scy &tx_seg1_idx) < 0) 2957346981Scy return; 2958346981Scy 2959346981Scy if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci, 2960346981Scy tx_chanwidth, tx_seg1_idx) != 0) { 2961346981Scy wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 2962346981Scy ocv_errorstr); 2963346981Scy return; 2964346981Scy } 2965346981Scy } 2966346981Scy#endif /* CONFIG_OCV */ 2967346981Scy#ifdef CONFIG_IEEE80211R_AP 2968346981Scy if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) { 2969346981Scy wpa_sta_disconnect(wpa_auth, sm->addr, 2970346981Scy WLAN_REASON_PREV_AUTH_NOT_VALID); 2971346981Scy return; 2972346981Scy } 2973346981Scy#endif /* CONFIG_IEEE80211R_AP */ 2974346981Scy#ifdef CONFIG_P2P 2975346981Scy if (kde.ip_addr_req && kde.ip_addr_req[0] && 2976346981Scy wpa_auth->ip_pool && WPA_GET_BE32(sm->ip_addr) == 0) { 2977346981Scy int idx; 2978346981Scy wpa_printf(MSG_DEBUG, 2979346981Scy "P2P: IP address requested in EAPOL-Key exchange"); 2980346981Scy idx = bitfield_get_first_zero(wpa_auth->ip_pool); 2981346981Scy if (idx >= 0) { 2982346981Scy u32 start = WPA_GET_BE32(wpa_auth->conf.ip_addr_start); 2983346981Scy bitfield_set(wpa_auth->ip_pool, idx); 2984346981Scy WPA_PUT_BE32(sm->ip_addr, start + idx); 2985346981Scy wpa_printf(MSG_DEBUG, 2986346981Scy "P2P: Assigned IP address %u.%u.%u.%u to " 2987346981Scy MACSTR, sm->ip_addr[0], sm->ip_addr[1], 2988346981Scy sm->ip_addr[2], sm->ip_addr[3], 2989346981Scy MAC2STR(sm->addr)); 2990346981Scy } 2991346981Scy } 2992346981Scy#endif /* CONFIG_P2P */ 2993346981Scy 2994346981Scy#ifdef CONFIG_IEEE80211R_AP 2995214501Srpaulo if (sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { 2996214501Srpaulo /* 2997214501Srpaulo * Verify that PMKR1Name from EAPOL-Key message 2/4 matches 2998214501Srpaulo * with the value we derived. 2999214501Srpaulo */ 3000281806Srpaulo if (os_memcmp_const(sm->sup_pmk_r1_name, sm->pmk_r1_name, 3001281806Srpaulo WPA_PMK_NAME_LEN) != 0) { 3002214501Srpaulo wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 3003214501Srpaulo "PMKR1Name mismatch in FT 4-way " 3004214501Srpaulo "handshake"); 3005214501Srpaulo wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from " 3006214501Srpaulo "Supplicant", 3007214501Srpaulo sm->sup_pmk_r1_name, WPA_PMK_NAME_LEN); 3008214501Srpaulo wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name", 3009214501Srpaulo sm->pmk_r1_name, WPA_PMK_NAME_LEN); 3010214501Srpaulo return; 3011214501Srpaulo } 3012214501Srpaulo } 3013346981Scy#endif /* CONFIG_IEEE80211R_AP */ 3014214501Srpaulo 3015346981Scy if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) && 3016346981Scy wpa_auth_update_vlan(wpa_auth, sm->addr, vlan_id) < 0) { 3017346981Scy wpa_sta_disconnect(wpa_auth, sm->addr, 3018346981Scy WLAN_REASON_PREV_AUTH_NOT_VALID); 3019346981Scy return; 3020346981Scy } 3021346981Scy 3022252726Srpaulo sm->pending_1_of_4_timeout = 0; 3023214501Srpaulo eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm); 3024214501Srpaulo 3025214501Srpaulo if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { 3026214501Srpaulo /* PSK may have changed from the previous choice, so update 3027214501Srpaulo * state machine data based on whatever PSK was selected here. 3028214501Srpaulo */ 3029214501Srpaulo os_memcpy(sm->PMK, pmk, PMK_LEN); 3030337817Scy sm->pmk_len = PMK_LEN; 3031214501Srpaulo } 3032214501Srpaulo 3033214501Srpaulo sm->MICVerified = TRUE; 3034214501Srpaulo 3035214501Srpaulo os_memcpy(&sm->PTK, &PTK, sizeof(PTK)); 3036351611Scy forced_memzero(&PTK, sizeof(PTK)); 3037214501Srpaulo sm->PTK_valid = TRUE; 3038214501Srpaulo} 3039214501Srpaulo 3040214501Srpaulo 3041214501SrpauloSM_STATE(WPA_PTK, PTKCALCNEGOTIATING2) 3042214501Srpaulo{ 3043214501Srpaulo SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING2, wpa_ptk); 3044214501Srpaulo sm->TimeoutCtr = 0; 3045214501Srpaulo} 3046214501Srpaulo 3047214501Srpaulo 3048214501Srpaulo#ifdef CONFIG_IEEE80211W 3049214501Srpaulo 3050214501Srpaulostatic int ieee80211w_kde_len(struct wpa_state_machine *sm) 3051214501Srpaulo{ 3052214501Srpaulo if (sm->mgmt_frame_prot) { 3053281806Srpaulo size_t len; 3054281806Srpaulo len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); 3055281806Srpaulo return 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN + len; 3056214501Srpaulo } 3057214501Srpaulo 3058214501Srpaulo return 0; 3059214501Srpaulo} 3060214501Srpaulo 3061214501Srpaulo 3062214501Srpaulostatic u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) 3063214501Srpaulo{ 3064214501Srpaulo struct wpa_igtk_kde igtk; 3065214501Srpaulo struct wpa_group *gsm = sm->group; 3066281806Srpaulo u8 rsc[WPA_KEY_RSC_LEN]; 3067281806Srpaulo size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); 3068214501Srpaulo 3069214501Srpaulo if (!sm->mgmt_frame_prot) 3070214501Srpaulo return pos; 3071214501Srpaulo 3072214501Srpaulo igtk.keyid[0] = gsm->GN_igtk; 3073214501Srpaulo igtk.keyid[1] = 0; 3074214501Srpaulo if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE || 3075281806Srpaulo wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, rsc) < 0) 3076214501Srpaulo os_memset(igtk.pn, 0, sizeof(igtk.pn)); 3077281806Srpaulo else 3078281806Srpaulo os_memcpy(igtk.pn, rsc, sizeof(igtk.pn)); 3079281806Srpaulo os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], len); 3080346981Scy if (sm->wpa_auth->conf.disable_gtk || 3081346981Scy sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { 3082252726Srpaulo /* 3083252726Srpaulo * Provide unique random IGTK to each STA to prevent use of 3084252726Srpaulo * IGTK in the BSS. 3085252726Srpaulo */ 3086281806Srpaulo if (random_get_bytes(igtk.igtk, len) < 0) 3087252726Srpaulo return pos; 3088252726Srpaulo } 3089214501Srpaulo pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK, 3090281806Srpaulo (const u8 *) &igtk, WPA_IGTK_KDE_PREFIX_LEN + len, 3091281806Srpaulo NULL, 0); 3092214501Srpaulo 3093214501Srpaulo return pos; 3094214501Srpaulo} 3095214501Srpaulo 3096214501Srpaulo#else /* CONFIG_IEEE80211W */ 3097214501Srpaulo 3098214501Srpaulostatic int ieee80211w_kde_len(struct wpa_state_machine *sm) 3099214501Srpaulo{ 3100214501Srpaulo return 0; 3101214501Srpaulo} 3102214501Srpaulo 3103214501Srpaulo 3104214501Srpaulostatic u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) 3105214501Srpaulo{ 3106214501Srpaulo return pos; 3107214501Srpaulo} 3108214501Srpaulo 3109214501Srpaulo#endif /* CONFIG_IEEE80211W */ 3110214501Srpaulo 3111214501Srpaulo 3112346981Scystatic int ocv_oci_len(struct wpa_state_machine *sm) 3113346981Scy{ 3114346981Scy#ifdef CONFIG_OCV 3115346981Scy if (wpa_auth_uses_ocv(sm)) 3116346981Scy return OCV_OCI_KDE_LEN; 3117346981Scy#endif /* CONFIG_OCV */ 3118346981Scy return 0; 3119346981Scy} 3120346981Scy 3121346981Scystatic int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos) 3122346981Scy{ 3123346981Scy#ifdef CONFIG_OCV 3124346981Scy struct wpa_channel_info ci; 3125346981Scy 3126346981Scy if (!wpa_auth_uses_ocv(sm)) 3127346981Scy return 0; 3128346981Scy 3129346981Scy if (wpa_channel_info(sm->wpa_auth, &ci) != 0) { 3130346981Scy wpa_printf(MSG_WARNING, 3131346981Scy "Failed to get channel info for OCI element"); 3132346981Scy return -1; 3133346981Scy } 3134346981Scy 3135346981Scy return ocv_insert_oci_kde(&ci, argpos); 3136346981Scy#else /* CONFIG_OCV */ 3137346981Scy return 0; 3138346981Scy#endif /* CONFIG_OCV */ 3139346981Scy} 3140346981Scy 3141346981Scy 3142214501SrpauloSM_STATE(WPA_PTK, PTKINITNEGOTIATING) 3143214501Srpaulo{ 3144252726Srpaulo u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos, dummy_gtk[32]; 3145214501Srpaulo size_t gtk_len, kde_len; 3146214501Srpaulo struct wpa_group *gsm = sm->group; 3147214501Srpaulo u8 *wpa_ie; 3148214501Srpaulo int wpa_ie_len, secure, keyidx, encr = 0; 3149214501Srpaulo 3150214501Srpaulo SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk); 3151214501Srpaulo sm->TimeoutEvt = FALSE; 3152214501Srpaulo 3153214501Srpaulo sm->TimeoutCtr++; 3154346981Scy if (sm->wpa_auth->conf.wpa_disable_eapol_key_retries && 3155346981Scy sm->TimeoutCtr > 1) { 3156346981Scy /* Do not allow retransmission of EAPOL-Key msg 3/4 */ 3157346981Scy return; 3158346981Scy } 3159346981Scy if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) { 3160214501Srpaulo /* No point in sending the EAPOL-Key - we will disconnect 3161214501Srpaulo * immediately following this. */ 3162214501Srpaulo return; 3163214501Srpaulo } 3164214501Srpaulo 3165214501Srpaulo /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE], 3166214501Srpaulo GTK[GN], IGTK, [FTIE], [TIE * 2]) 3167214501Srpaulo */ 3168214501Srpaulo os_memset(rsc, 0, WPA_KEY_RSC_LEN); 3169214501Srpaulo wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc); 3170214501Srpaulo /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */ 3171214501Srpaulo wpa_ie = sm->wpa_auth->wpa_ie; 3172214501Srpaulo wpa_ie_len = sm->wpa_auth->wpa_ie_len; 3173214501Srpaulo if (sm->wpa == WPA_VERSION_WPA && 3174214501Srpaulo (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) && 3175214501Srpaulo wpa_ie_len > wpa_ie[1] + 2 && wpa_ie[0] == WLAN_EID_RSN) { 3176281806Srpaulo /* WPA-only STA, remove RSN IE and possible MDIE */ 3177214501Srpaulo wpa_ie = wpa_ie + wpa_ie[1] + 2; 3178281806Srpaulo if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN) 3179281806Srpaulo wpa_ie = wpa_ie + wpa_ie[1] + 2; 3180214501Srpaulo wpa_ie_len = wpa_ie[1] + 2; 3181214501Srpaulo } 3182214501Srpaulo wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 3183214501Srpaulo "sending 3/4 msg of 4-Way Handshake"); 3184214501Srpaulo if (sm->wpa == WPA_VERSION_WPA2) { 3185214501Srpaulo /* WPA2 send GTK in the 4-way handshake */ 3186214501Srpaulo secure = 1; 3187214501Srpaulo gtk = gsm->GTK[gsm->GN - 1]; 3188214501Srpaulo gtk_len = gsm->GTK_len; 3189346981Scy if (sm->wpa_auth->conf.disable_gtk || 3190346981Scy sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { 3191252726Srpaulo /* 3192252726Srpaulo * Provide unique random GTK to each STA to prevent use 3193252726Srpaulo * of GTK in the BSS. 3194252726Srpaulo */ 3195252726Srpaulo if (random_get_bytes(dummy_gtk, gtk_len) < 0) 3196252726Srpaulo return; 3197252726Srpaulo gtk = dummy_gtk; 3198252726Srpaulo } 3199214501Srpaulo keyidx = gsm->GN; 3200214501Srpaulo _rsc = rsc; 3201214501Srpaulo encr = 1; 3202214501Srpaulo } else { 3203214501Srpaulo /* WPA does not include GTK in msg 3/4 */ 3204214501Srpaulo secure = 0; 3205214501Srpaulo gtk = NULL; 3206214501Srpaulo gtk_len = 0; 3207214501Srpaulo keyidx = 0; 3208214501Srpaulo _rsc = NULL; 3209252726Srpaulo if (sm->rx_eapol_key_secure) { 3210252726Srpaulo /* 3211252726Srpaulo * It looks like Windows 7 supplicant tries to use 3212252726Srpaulo * Secure bit in msg 2/4 after having reported Michael 3213252726Srpaulo * MIC failure and it then rejects the 4-way handshake 3214252726Srpaulo * if msg 3/4 does not set Secure bit. Work around this 3215252726Srpaulo * by setting the Secure bit here even in the case of 3216252726Srpaulo * WPA if the supplicant used it first. 3217252726Srpaulo */ 3218252726Srpaulo wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 3219252726Srpaulo "STA used Secure bit in WPA msg 2/4 - " 3220252726Srpaulo "set Secure for 3/4 as workaround"); 3221252726Srpaulo secure = 1; 3222252726Srpaulo } 3223214501Srpaulo } 3224214501Srpaulo 3225346981Scy kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm); 3226214501Srpaulo if (gtk) 3227214501Srpaulo kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len; 3228346981Scy#ifdef CONFIG_IEEE80211R_AP 3229214501Srpaulo if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { 3230214501Srpaulo kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */ 3231214501Srpaulo kde_len += 300; /* FTIE + 2 * TIE */ 3232214501Srpaulo } 3233346981Scy#endif /* CONFIG_IEEE80211R_AP */ 3234281806Srpaulo#ifdef CONFIG_P2P 3235281806Srpaulo if (WPA_GET_BE32(sm->ip_addr) > 0) 3236281806Srpaulo kde_len += 2 + RSN_SELECTOR_LEN + 3 * 4; 3237281806Srpaulo#endif /* CONFIG_P2P */ 3238214501Srpaulo kde = os_malloc(kde_len); 3239214501Srpaulo if (kde == NULL) 3240214501Srpaulo return; 3241214501Srpaulo 3242214501Srpaulo pos = kde; 3243214501Srpaulo os_memcpy(pos, wpa_ie, wpa_ie_len); 3244214501Srpaulo pos += wpa_ie_len; 3245346981Scy#ifdef CONFIG_IEEE80211R_AP 3246214501Srpaulo if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { 3247337817Scy int res; 3248337817Scy size_t elen; 3249337817Scy 3250337817Scy elen = pos - kde; 3251337817Scy res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name); 3252214501Srpaulo if (res < 0) { 3253214501Srpaulo wpa_printf(MSG_ERROR, "FT: Failed to insert " 3254214501Srpaulo "PMKR1Name into RSN IE in EAPOL-Key data"); 3255214501Srpaulo os_free(kde); 3256214501Srpaulo return; 3257214501Srpaulo } 3258337817Scy pos -= wpa_ie_len; 3259337817Scy pos += elen; 3260214501Srpaulo } 3261346981Scy#endif /* CONFIG_IEEE80211R_AP */ 3262214501Srpaulo if (gtk) { 3263214501Srpaulo u8 hdr[2]; 3264214501Srpaulo hdr[0] = keyidx & 0x03; 3265214501Srpaulo hdr[1] = 0; 3266214501Srpaulo pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, 3267214501Srpaulo gtk, gtk_len); 3268214501Srpaulo } 3269214501Srpaulo pos = ieee80211w_kde_add(sm, pos); 3270346981Scy if (ocv_oci_add(sm, &pos) < 0) { 3271346981Scy os_free(kde); 3272346981Scy return; 3273346981Scy } 3274214501Srpaulo 3275346981Scy#ifdef CONFIG_IEEE80211R_AP 3276214501Srpaulo if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { 3277214501Srpaulo int res; 3278214501Srpaulo struct wpa_auth_config *conf; 3279214501Srpaulo 3280214501Srpaulo conf = &sm->wpa_auth->conf; 3281337817Scy if (sm->assoc_resp_ftie && 3282337817Scy kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) { 3283337817Scy os_memcpy(pos, sm->assoc_resp_ftie, 3284337817Scy 2 + sm->assoc_resp_ftie[1]); 3285337817Scy res = 2 + sm->assoc_resp_ftie[1]; 3286337817Scy } else { 3287346981Scy int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt); 3288346981Scy 3289346981Scy res = wpa_write_ftie(conf, use_sha384, 3290346981Scy conf->r0_key_holder, 3291337817Scy conf->r0_key_holder_len, 3292337817Scy NULL, NULL, pos, 3293337817Scy kde + kde_len - pos, 3294337817Scy NULL, 0); 3295337817Scy } 3296214501Srpaulo if (res < 0) { 3297214501Srpaulo wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE " 3298214501Srpaulo "into EAPOL-Key Key Data"); 3299214501Srpaulo os_free(kde); 3300214501Srpaulo return; 3301214501Srpaulo } 3302214501Srpaulo pos += res; 3303214501Srpaulo 3304214501Srpaulo /* TIE[ReassociationDeadline] (TU) */ 3305214501Srpaulo *pos++ = WLAN_EID_TIMEOUT_INTERVAL; 3306214501Srpaulo *pos++ = 5; 3307214501Srpaulo *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE; 3308214501Srpaulo WPA_PUT_LE32(pos, conf->reassociation_deadline); 3309214501Srpaulo pos += 4; 3310214501Srpaulo 3311214501Srpaulo /* TIE[KeyLifetime] (seconds) */ 3312214501Srpaulo *pos++ = WLAN_EID_TIMEOUT_INTERVAL; 3313214501Srpaulo *pos++ = 5; 3314214501Srpaulo *pos++ = WLAN_TIMEOUT_KEY_LIFETIME; 3315346981Scy WPA_PUT_LE32(pos, conf->r0_key_lifetime); 3316214501Srpaulo pos += 4; 3317214501Srpaulo } 3318346981Scy#endif /* CONFIG_IEEE80211R_AP */ 3319281806Srpaulo#ifdef CONFIG_P2P 3320281806Srpaulo if (WPA_GET_BE32(sm->ip_addr) > 0) { 3321281806Srpaulo u8 addr[3 * 4]; 3322281806Srpaulo os_memcpy(addr, sm->ip_addr, 4); 3323281806Srpaulo os_memcpy(addr + 4, sm->wpa_auth->conf.ip_addr_mask, 4); 3324281806Srpaulo os_memcpy(addr + 8, sm->wpa_auth->conf.ip_addr_go, 4); 3325281806Srpaulo pos = wpa_add_kde(pos, WFA_KEY_DATA_IP_ADDR_ALLOC, 3326281806Srpaulo addr, sizeof(addr), NULL, 0); 3327281806Srpaulo } 3328281806Srpaulo#endif /* CONFIG_P2P */ 3329214501Srpaulo 3330214501Srpaulo wpa_send_eapol(sm->wpa_auth, sm, 3331346981Scy (secure ? WPA_KEY_INFO_SECURE : 0) | 3332346981Scy (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ? 3333346981Scy WPA_KEY_INFO_MIC : 0) | 3334214501Srpaulo WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL | 3335214501Srpaulo WPA_KEY_INFO_KEY_TYPE, 3336214501Srpaulo _rsc, sm->ANonce, kde, pos - kde, keyidx, encr); 3337214501Srpaulo os_free(kde); 3338214501Srpaulo} 3339214501Srpaulo 3340214501Srpaulo 3341214501SrpauloSM_STATE(WPA_PTK, PTKINITDONE) 3342214501Srpaulo{ 3343214501Srpaulo SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk); 3344214501Srpaulo sm->EAPOLKeyReceived = FALSE; 3345214501Srpaulo if (sm->Pair) { 3346252726Srpaulo enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise); 3347252726Srpaulo int klen = wpa_cipher_key_len(sm->pairwise); 3348214501Srpaulo if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, 3349281806Srpaulo sm->PTK.tk, klen)) { 3350346981Scy wpa_sta_disconnect(sm->wpa_auth, sm->addr, 3351346981Scy WLAN_REASON_PREV_AUTH_NOT_VALID); 3352214501Srpaulo return; 3353214501Srpaulo } 3354214501Srpaulo /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ 3355214501Srpaulo sm->pairwise_set = TRUE; 3356214501Srpaulo 3357346981Scy wpa_auth_set_ptk_rekey_timer(sm); 3358214501Srpaulo 3359346981Scy if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) || 3360346981Scy sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP || 3361346981Scy sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) { 3362214501Srpaulo wpa_auth_set_eapol(sm->wpa_auth, sm->addr, 3363214501Srpaulo WPA_EAPOL_authorized, 1); 3364214501Srpaulo } 3365214501Srpaulo } 3366214501Srpaulo 3367214501Srpaulo if (0 /* IBSS == TRUE */) { 3368214501Srpaulo sm->keycount++; 3369214501Srpaulo if (sm->keycount == 2) { 3370214501Srpaulo wpa_auth_set_eapol(sm->wpa_auth, sm->addr, 3371214501Srpaulo WPA_EAPOL_portValid, 1); 3372214501Srpaulo } 3373214501Srpaulo } else { 3374214501Srpaulo wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 3375214501Srpaulo 1); 3376214501Srpaulo } 3377214501Srpaulo wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyAvailable, 0); 3378214501Srpaulo wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyDone, 1); 3379214501Srpaulo if (sm->wpa == WPA_VERSION_WPA) 3380214501Srpaulo sm->PInitAKeys = TRUE; 3381214501Srpaulo else 3382214501Srpaulo sm->has_GTK = TRUE; 3383214501Srpaulo wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, 3384214501Srpaulo "pairwise key handshake completed (%s)", 3385214501Srpaulo sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN"); 3386214501Srpaulo 3387346981Scy#ifdef CONFIG_IEEE80211R_AP 3388214501Srpaulo wpa_ft_push_pmk_r1(sm->wpa_auth, sm->addr); 3389346981Scy#endif /* CONFIG_IEEE80211R_AP */ 3390214501Srpaulo} 3391214501Srpaulo 3392214501Srpaulo 3393214501SrpauloSM_STEP(WPA_PTK) 3394214501Srpaulo{ 3395214501Srpaulo struct wpa_authenticator *wpa_auth = sm->wpa_auth; 3396214501Srpaulo 3397214501Srpaulo if (sm->Init) 3398214501Srpaulo SM_ENTER(WPA_PTK, INITIALIZE); 3399214501Srpaulo else if (sm->Disconnect 3400252726Srpaulo /* || FIX: dot11RSNAConfigSALifetime timeout */) { 3401252726Srpaulo wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, 3402252726Srpaulo "WPA_PTK: sm->Disconnect"); 3403214501Srpaulo SM_ENTER(WPA_PTK, DISCONNECT); 3404252726Srpaulo } 3405214501Srpaulo else if (sm->DeauthenticationRequest) 3406214501Srpaulo SM_ENTER(WPA_PTK, DISCONNECTED); 3407214501Srpaulo else if (sm->AuthenticationRequest) 3408214501Srpaulo SM_ENTER(WPA_PTK, AUTHENTICATION); 3409214501Srpaulo else if (sm->ReAuthenticationRequest) 3410214501Srpaulo SM_ENTER(WPA_PTK, AUTHENTICATION2); 3411324697Sgordon else if (sm->PTKRequest) { 3412324697Sgordon if (wpa_auth_sm_ptk_update(sm) < 0) 3413324697Sgordon SM_ENTER(WPA_PTK, DISCONNECTED); 3414324697Sgordon else 3415324697Sgordon SM_ENTER(WPA_PTK, PTKSTART); 3416324697Sgordon } else switch (sm->wpa_ptk_state) { 3417214501Srpaulo case WPA_PTK_INITIALIZE: 3418214501Srpaulo break; 3419214501Srpaulo case WPA_PTK_DISCONNECT: 3420214501Srpaulo SM_ENTER(WPA_PTK, DISCONNECTED); 3421214501Srpaulo break; 3422214501Srpaulo case WPA_PTK_DISCONNECTED: 3423214501Srpaulo SM_ENTER(WPA_PTK, INITIALIZE); 3424214501Srpaulo break; 3425214501Srpaulo case WPA_PTK_AUTHENTICATION: 3426214501Srpaulo SM_ENTER(WPA_PTK, AUTHENTICATION2); 3427214501Srpaulo break; 3428214501Srpaulo case WPA_PTK_AUTHENTICATION2: 3429214501Srpaulo if (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) && 3430214501Srpaulo wpa_auth_get_eapol(sm->wpa_auth, sm->addr, 3431214501Srpaulo WPA_EAPOL_keyRun) > 0) 3432214501Srpaulo SM_ENTER(WPA_PTK, INITPMK); 3433346981Scy else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) || 3434346981Scy sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE 3435214501Srpaulo /* FIX: && 802.1X::keyRun */) 3436214501Srpaulo SM_ENTER(WPA_PTK, INITPSK); 3437346981Scy else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) 3438346981Scy SM_ENTER(WPA_PTK, INITPMK); 3439214501Srpaulo break; 3440214501Srpaulo case WPA_PTK_INITPMK: 3441214501Srpaulo if (wpa_auth_get_eapol(sm->wpa_auth, sm->addr, 3442346981Scy WPA_EAPOL_keyAvailable) > 0) { 3443214501Srpaulo SM_ENTER(WPA_PTK, PTKSTART); 3444346981Scy#ifdef CONFIG_DPP 3445346981Scy } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->pmksa) { 3446346981Scy SM_ENTER(WPA_PTK, PTKSTART); 3447346981Scy#endif /* CONFIG_DPP */ 3448346981Scy } else { 3449214501Srpaulo wpa_auth->dot11RSNA4WayHandshakeFailures++; 3450252726Srpaulo wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, 3451252726Srpaulo "INITPMK - keyAvailable = false"); 3452214501Srpaulo SM_ENTER(WPA_PTK, DISCONNECT); 3453214501Srpaulo } 3454214501Srpaulo break; 3455214501Srpaulo case WPA_PTK_INITPSK: 3456281806Srpaulo if (wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, 3457346981Scy NULL, NULL, NULL)) { 3458214501Srpaulo SM_ENTER(WPA_PTK, PTKSTART); 3459346981Scy#ifdef CONFIG_SAE 3460346981Scy } else if (wpa_auth_uses_sae(sm) && sm->pmksa) { 3461346981Scy SM_ENTER(WPA_PTK, PTKSTART); 3462346981Scy#endif /* CONFIG_SAE */ 3463346981Scy } else { 3464214501Srpaulo wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, 3465214501Srpaulo "no PSK configured for the STA"); 3466214501Srpaulo wpa_auth->dot11RSNA4WayHandshakeFailures++; 3467214501Srpaulo SM_ENTER(WPA_PTK, DISCONNECT); 3468214501Srpaulo } 3469214501Srpaulo break; 3470214501Srpaulo case WPA_PTK_PTKSTART: 3471214501Srpaulo if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && 3472214501Srpaulo sm->EAPOLKeyPairwise) 3473214501Srpaulo SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); 3474214501Srpaulo else if (sm->TimeoutCtr > 3475346981Scy sm->wpa_auth->conf.wpa_pairwise_update_count) { 3476214501Srpaulo wpa_auth->dot11RSNA4WayHandshakeFailures++; 3477346981Scy wpa_auth_vlogger( 3478346981Scy sm->wpa_auth, sm->addr, LOGGER_DEBUG, 3479346981Scy "PTKSTART: Retry limit %u reached", 3480346981Scy sm->wpa_auth->conf.wpa_pairwise_update_count); 3481214501Srpaulo SM_ENTER(WPA_PTK, DISCONNECT); 3482214501Srpaulo } else if (sm->TimeoutEvt) 3483214501Srpaulo SM_ENTER(WPA_PTK, PTKSTART); 3484214501Srpaulo break; 3485214501Srpaulo case WPA_PTK_PTKCALCNEGOTIATING: 3486214501Srpaulo if (sm->MICVerified) 3487214501Srpaulo SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING2); 3488214501Srpaulo else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && 3489214501Srpaulo sm->EAPOLKeyPairwise) 3490214501Srpaulo SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); 3491214501Srpaulo else if (sm->TimeoutEvt) 3492214501Srpaulo SM_ENTER(WPA_PTK, PTKSTART); 3493214501Srpaulo break; 3494214501Srpaulo case WPA_PTK_PTKCALCNEGOTIATING2: 3495214501Srpaulo SM_ENTER(WPA_PTK, PTKINITNEGOTIATING); 3496214501Srpaulo break; 3497214501Srpaulo case WPA_PTK_PTKINITNEGOTIATING: 3498252726Srpaulo if (sm->update_snonce) 3499252726Srpaulo SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); 3500252726Srpaulo else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && 3501252726Srpaulo sm->EAPOLKeyPairwise && sm->MICVerified) 3502214501Srpaulo SM_ENTER(WPA_PTK, PTKINITDONE); 3503214501Srpaulo else if (sm->TimeoutCtr > 3504346981Scy sm->wpa_auth->conf.wpa_pairwise_update_count || 3505346981Scy (sm->wpa_auth->conf.wpa_disable_eapol_key_retries && 3506346981Scy sm->TimeoutCtr > 1)) { 3507214501Srpaulo wpa_auth->dot11RSNA4WayHandshakeFailures++; 3508346981Scy wpa_auth_vlogger( 3509346981Scy sm->wpa_auth, sm->addr, LOGGER_DEBUG, 3510346981Scy "PTKINITNEGOTIATING: Retry limit %u reached", 3511346981Scy sm->wpa_auth->conf.wpa_pairwise_update_count); 3512214501Srpaulo SM_ENTER(WPA_PTK, DISCONNECT); 3513214501Srpaulo } else if (sm->TimeoutEvt) 3514214501Srpaulo SM_ENTER(WPA_PTK, PTKINITNEGOTIATING); 3515214501Srpaulo break; 3516214501Srpaulo case WPA_PTK_PTKINITDONE: 3517214501Srpaulo break; 3518214501Srpaulo } 3519214501Srpaulo} 3520214501Srpaulo 3521214501Srpaulo 3522214501SrpauloSM_STATE(WPA_PTK_GROUP, IDLE) 3523214501Srpaulo{ 3524214501Srpaulo SM_ENTRY_MA(WPA_PTK_GROUP, IDLE, wpa_ptk_group); 3525214501Srpaulo if (sm->Init) { 3526214501Srpaulo /* Init flag is not cleared here, so avoid busy 3527214501Srpaulo * loop by claiming nothing changed. */ 3528214501Srpaulo sm->changed = FALSE; 3529214501Srpaulo } 3530214501Srpaulo sm->GTimeoutCtr = 0; 3531214501Srpaulo} 3532214501Srpaulo 3533214501Srpaulo 3534214501SrpauloSM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) 3535214501Srpaulo{ 3536214501Srpaulo u8 rsc[WPA_KEY_RSC_LEN]; 3537214501Srpaulo struct wpa_group *gsm = sm->group; 3538281806Srpaulo const u8 *kde; 3539281806Srpaulo u8 *kde_buf = NULL, *pos, hdr[2]; 3540214501Srpaulo size_t kde_len; 3541252726Srpaulo u8 *gtk, dummy_gtk[32]; 3542214501Srpaulo 3543214501Srpaulo SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group); 3544214501Srpaulo 3545214501Srpaulo sm->GTimeoutCtr++; 3546346981Scy if (sm->wpa_auth->conf.wpa_disable_eapol_key_retries && 3547346981Scy sm->GTimeoutCtr > 1) { 3548346981Scy /* Do not allow retransmission of EAPOL-Key group msg 1/2 */ 3549346981Scy return; 3550346981Scy } 3551346981Scy if (sm->GTimeoutCtr > sm->wpa_auth->conf.wpa_group_update_count) { 3552214501Srpaulo /* No point in sending the EAPOL-Key - we will disconnect 3553214501Srpaulo * immediately following this. */ 3554214501Srpaulo return; 3555214501Srpaulo } 3556214501Srpaulo 3557214501Srpaulo if (sm->wpa == WPA_VERSION_WPA) 3558214501Srpaulo sm->PInitAKeys = FALSE; 3559214501Srpaulo sm->TimeoutEvt = FALSE; 3560214501Srpaulo /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */ 3561214501Srpaulo os_memset(rsc, 0, WPA_KEY_RSC_LEN); 3562214501Srpaulo if (gsm->wpa_group_state == WPA_GROUP_SETKEYSDONE) 3563214501Srpaulo wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc); 3564214501Srpaulo wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 3565214501Srpaulo "sending 1/2 msg of Group Key Handshake"); 3566214501Srpaulo 3567252726Srpaulo gtk = gsm->GTK[gsm->GN - 1]; 3568346981Scy if (sm->wpa_auth->conf.disable_gtk || 3569346981Scy sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { 3570252726Srpaulo /* 3571252726Srpaulo * Provide unique random GTK to each STA to prevent use 3572252726Srpaulo * of GTK in the BSS. 3573252726Srpaulo */ 3574252726Srpaulo if (random_get_bytes(dummy_gtk, gsm->GTK_len) < 0) 3575252726Srpaulo return; 3576252726Srpaulo gtk = dummy_gtk; 3577252726Srpaulo } 3578214501Srpaulo if (sm->wpa == WPA_VERSION_WPA2) { 3579214501Srpaulo kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len + 3580346981Scy ieee80211w_kde_len(sm) + ocv_oci_len(sm); 3581281806Srpaulo kde_buf = os_malloc(kde_len); 3582281806Srpaulo if (kde_buf == NULL) 3583214501Srpaulo return; 3584214501Srpaulo 3585281806Srpaulo kde = pos = kde_buf; 3586214501Srpaulo hdr[0] = gsm->GN & 0x03; 3587214501Srpaulo hdr[1] = 0; 3588214501Srpaulo pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, 3589252726Srpaulo gtk, gsm->GTK_len); 3590214501Srpaulo pos = ieee80211w_kde_add(sm, pos); 3591346981Scy if (ocv_oci_add(sm, &pos) < 0) { 3592346981Scy os_free(kde_buf); 3593346981Scy return; 3594346981Scy } 3595281806Srpaulo kde_len = pos - kde; 3596214501Srpaulo } else { 3597252726Srpaulo kde = gtk; 3598281806Srpaulo kde_len = gsm->GTK_len; 3599214501Srpaulo } 3600214501Srpaulo 3601214501Srpaulo wpa_send_eapol(sm->wpa_auth, sm, 3602346981Scy WPA_KEY_INFO_SECURE | 3603346981Scy (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ? 3604346981Scy WPA_KEY_INFO_MIC : 0) | 3605214501Srpaulo WPA_KEY_INFO_ACK | 3606214501Srpaulo (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0), 3607346981Scy rsc, NULL, kde, kde_len, gsm->GN, 1); 3608281806Srpaulo 3609281806Srpaulo os_free(kde_buf); 3610214501Srpaulo} 3611214501Srpaulo 3612214501Srpaulo 3613214501SrpauloSM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED) 3614214501Srpaulo{ 3615346981Scy#ifdef CONFIG_OCV 3616346981Scy struct wpa_authenticator *wpa_auth = sm->wpa_auth; 3617346981Scy const u8 *key_data, *mic; 3618346981Scy struct ieee802_1x_hdr *hdr; 3619346981Scy struct wpa_eapol_key *key; 3620346981Scy struct wpa_eapol_ie_parse kde; 3621346981Scy size_t mic_len; 3622346981Scy u16 key_data_length; 3623346981Scy#endif /* CONFIG_OCV */ 3624346981Scy 3625214501Srpaulo SM_ENTRY_MA(WPA_PTK_GROUP, REKEYESTABLISHED, wpa_ptk_group); 3626214501Srpaulo sm->EAPOLKeyReceived = FALSE; 3627346981Scy 3628346981Scy#ifdef CONFIG_OCV 3629346981Scy mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len); 3630346981Scy 3631346981Scy /* 3632346981Scy * Note: last_rx_eapol_key length fields have already been validated in 3633346981Scy * wpa_receive(). 3634346981Scy */ 3635346981Scy hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key; 3636346981Scy key = (struct wpa_eapol_key *) (hdr + 1); 3637346981Scy mic = (u8 *) (key + 1); 3638346981Scy key_data = mic + mic_len + 2; 3639346981Scy key_data_length = WPA_GET_BE16(mic + mic_len); 3640346981Scy if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) - 3641346981Scy sizeof(*key) - mic_len - 2) 3642346981Scy return; 3643346981Scy 3644346981Scy if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) { 3645346981Scy wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, 3646346981Scy "received EAPOL-Key group msg 2/2 with invalid Key Data contents"); 3647346981Scy return; 3648346981Scy } 3649346981Scy 3650346981Scy if (wpa_auth_uses_ocv(sm)) { 3651346981Scy struct wpa_channel_info ci; 3652346981Scy int tx_chanwidth; 3653346981Scy int tx_seg1_idx; 3654346981Scy 3655346981Scy if (wpa_channel_info(wpa_auth, &ci) != 0) { 3656346981Scy wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 3657346981Scy "Failed to get channel info to validate received OCI in EAPOL-Key group 1/2"); 3658346981Scy return; 3659346981Scy } 3660346981Scy 3661346981Scy if (get_sta_tx_parameters(sm, 3662346981Scy channel_width_to_int(ci.chanwidth), 3663346981Scy ci.seg1_idx, &tx_chanwidth, 3664346981Scy &tx_seg1_idx) < 0) 3665346981Scy return; 3666346981Scy 3667346981Scy if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci, 3668346981Scy tx_chanwidth, tx_seg1_idx) != 0) { 3669346981Scy wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, 3670346981Scy ocv_errorstr); 3671346981Scy return; 3672346981Scy } 3673346981Scy } 3674346981Scy#endif /* CONFIG_OCV */ 3675346981Scy 3676214501Srpaulo if (sm->GUpdateStationKeys) 3677214501Srpaulo sm->group->GKeyDoneStations--; 3678214501Srpaulo sm->GUpdateStationKeys = FALSE; 3679214501Srpaulo sm->GTimeoutCtr = 0; 3680214501Srpaulo /* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */ 3681214501Srpaulo wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, 3682214501Srpaulo "group key handshake completed (%s)", 3683214501Srpaulo sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN"); 3684214501Srpaulo sm->has_GTK = TRUE; 3685214501Srpaulo} 3686214501Srpaulo 3687214501Srpaulo 3688214501SrpauloSM_STATE(WPA_PTK_GROUP, KEYERROR) 3689214501Srpaulo{ 3690214501Srpaulo SM_ENTRY_MA(WPA_PTK_GROUP, KEYERROR, wpa_ptk_group); 3691214501Srpaulo if (sm->GUpdateStationKeys) 3692214501Srpaulo sm->group->GKeyDoneStations--; 3693214501Srpaulo sm->GUpdateStationKeys = FALSE; 3694214501Srpaulo sm->Disconnect = TRUE; 3695346981Scy wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, 3696346981Scy "group key handshake failed (%s) after %u tries", 3697346981Scy sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN", 3698346981Scy sm->wpa_auth->conf.wpa_group_update_count); 3699214501Srpaulo} 3700214501Srpaulo 3701214501Srpaulo 3702214501SrpauloSM_STEP(WPA_PTK_GROUP) 3703214501Srpaulo{ 3704214501Srpaulo if (sm->Init || sm->PtkGroupInit) { 3705214501Srpaulo SM_ENTER(WPA_PTK_GROUP, IDLE); 3706214501Srpaulo sm->PtkGroupInit = FALSE; 3707214501Srpaulo } else switch (sm->wpa_ptk_group_state) { 3708214501Srpaulo case WPA_PTK_GROUP_IDLE: 3709214501Srpaulo if (sm->GUpdateStationKeys || 3710214501Srpaulo (sm->wpa == WPA_VERSION_WPA && sm->PInitAKeys)) 3711214501Srpaulo SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING); 3712214501Srpaulo break; 3713214501Srpaulo case WPA_PTK_GROUP_REKEYNEGOTIATING: 3714214501Srpaulo if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && 3715214501Srpaulo !sm->EAPOLKeyPairwise && sm->MICVerified) 3716214501Srpaulo SM_ENTER(WPA_PTK_GROUP, REKEYESTABLISHED); 3717214501Srpaulo else if (sm->GTimeoutCtr > 3718346981Scy sm->wpa_auth->conf.wpa_group_update_count || 3719346981Scy (sm->wpa_auth->conf.wpa_disable_eapol_key_retries && 3720346981Scy sm->GTimeoutCtr > 1)) 3721214501Srpaulo SM_ENTER(WPA_PTK_GROUP, KEYERROR); 3722214501Srpaulo else if (sm->TimeoutEvt) 3723214501Srpaulo SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING); 3724214501Srpaulo break; 3725214501Srpaulo case WPA_PTK_GROUP_KEYERROR: 3726214501Srpaulo SM_ENTER(WPA_PTK_GROUP, IDLE); 3727214501Srpaulo break; 3728214501Srpaulo case WPA_PTK_GROUP_REKEYESTABLISHED: 3729214501Srpaulo SM_ENTER(WPA_PTK_GROUP, IDLE); 3730214501Srpaulo break; 3731214501Srpaulo } 3732214501Srpaulo} 3733214501Srpaulo 3734214501Srpaulo 3735214501Srpaulostatic int wpa_gtk_update(struct wpa_authenticator *wpa_auth, 3736214501Srpaulo struct wpa_group *group) 3737214501Srpaulo{ 3738214501Srpaulo int ret = 0; 3739214501Srpaulo 3740214501Srpaulo os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); 3741214501Srpaulo inc_byte_array(group->Counter, WPA_NONCE_LEN); 3742252726Srpaulo if (wpa_gmk_to_gtk(group->GMK, "Group key expansion", 3743252726Srpaulo wpa_auth->addr, group->GNonce, 3744252726Srpaulo group->GTK[group->GN - 1], group->GTK_len) < 0) 3745252726Srpaulo ret = -1; 3746252726Srpaulo wpa_hexdump_key(MSG_DEBUG, "GTK", 3747252726Srpaulo group->GTK[group->GN - 1], group->GTK_len); 3748214501Srpaulo 3749214501Srpaulo#ifdef CONFIG_IEEE80211W 3750214501Srpaulo if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) { 3751281806Srpaulo size_t len; 3752281806Srpaulo len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher); 3753252726Srpaulo os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); 3754252726Srpaulo inc_byte_array(group->Counter, WPA_NONCE_LEN); 3755252726Srpaulo if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion", 3756252726Srpaulo wpa_auth->addr, group->GNonce, 3757281806Srpaulo group->IGTK[group->GN_igtk - 4], len) < 0) 3758214501Srpaulo ret = -1; 3759214501Srpaulo wpa_hexdump_key(MSG_DEBUG, "IGTK", 3760281806Srpaulo group->IGTK[group->GN_igtk - 4], len); 3761214501Srpaulo } 3762214501Srpaulo#endif /* CONFIG_IEEE80211W */ 3763214501Srpaulo 3764214501Srpaulo return ret; 3765214501Srpaulo} 3766214501Srpaulo 3767214501Srpaulo 3768214501Srpaulostatic void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth, 3769214501Srpaulo struct wpa_group *group) 3770214501Srpaulo{ 3771214501Srpaulo wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " 3772214501Srpaulo "GTK_INIT (VLAN-ID %d)", group->vlan_id); 3773214501Srpaulo group->changed = FALSE; /* GInit is not cleared here; avoid loop */ 3774214501Srpaulo group->wpa_group_state = WPA_GROUP_GTK_INIT; 3775214501Srpaulo 3776214501Srpaulo /* GTK[0..N] = 0 */ 3777214501Srpaulo os_memset(group->GTK, 0, sizeof(group->GTK)); 3778214501Srpaulo group->GN = 1; 3779214501Srpaulo group->GM = 2; 3780214501Srpaulo#ifdef CONFIG_IEEE80211W 3781214501Srpaulo group->GN_igtk = 4; 3782214501Srpaulo group->GM_igtk = 5; 3783214501Srpaulo#endif /* CONFIG_IEEE80211W */ 3784214501Srpaulo /* GTK[GN] = CalcGTK() */ 3785214501Srpaulo wpa_gtk_update(wpa_auth, group); 3786214501Srpaulo} 3787214501Srpaulo 3788214501Srpaulo 3789214501Srpaulostatic int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx) 3790214501Srpaulo{ 3791252726Srpaulo if (ctx != NULL && ctx != sm->group) 3792252726Srpaulo return 0; 3793252726Srpaulo 3794214501Srpaulo if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) { 3795214501Srpaulo wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 3796214501Srpaulo "Not in PTKINITDONE; skip Group Key update"); 3797252726Srpaulo sm->GUpdateStationKeys = FALSE; 3798214501Srpaulo return 0; 3799214501Srpaulo } 3800214501Srpaulo if (sm->GUpdateStationKeys) { 3801214501Srpaulo /* 3802252726Srpaulo * This should not really happen, so add a debug log entry. 3803252726Srpaulo * Since we clear the GKeyDoneStations before the loop, the 3804252726Srpaulo * station needs to be counted here anyway. 3805214501Srpaulo */ 3806214501Srpaulo wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 3807252726Srpaulo "GUpdateStationKeys was already set when " 3808252726Srpaulo "marking station for GTK rekeying"); 3809214501Srpaulo } 3810252726Srpaulo 3811252726Srpaulo /* Do not rekey GTK/IGTK when STA is in WNM-Sleep Mode */ 3812252726Srpaulo if (sm->is_wnmsleep) 3813252726Srpaulo return 0; 3814252726Srpaulo 3815252726Srpaulo sm->group->GKeyDoneStations++; 3816252726Srpaulo sm->GUpdateStationKeys = TRUE; 3817252726Srpaulo 3818214501Srpaulo wpa_sm_step(sm); 3819214501Srpaulo return 0; 3820214501Srpaulo} 3821214501Srpaulo 3822214501Srpaulo 3823346981Scy#ifdef CONFIG_WNM_AP 3824252726Srpaulo/* update GTK when exiting WNM-Sleep Mode */ 3825252726Srpaulovoid wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm) 3826252726Srpaulo{ 3827281806Srpaulo if (sm == NULL || sm->is_wnmsleep) 3828252726Srpaulo return; 3829252726Srpaulo 3830252726Srpaulo wpa_group_update_sta(sm, NULL); 3831252726Srpaulo} 3832252726Srpaulo 3833252726Srpaulo 3834252726Srpaulovoid wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag) 3835252726Srpaulo{ 3836281806Srpaulo if (sm) 3837281806Srpaulo sm->is_wnmsleep = !!flag; 3838252726Srpaulo} 3839252726Srpaulo 3840252726Srpaulo 3841252726Srpauloint wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos) 3842252726Srpaulo{ 3843252726Srpaulo struct wpa_group *gsm = sm->group; 3844252726Srpaulo u8 *start = pos; 3845252726Srpaulo 3846252726Srpaulo /* 3847252726Srpaulo * GTK subelement: 3848252726Srpaulo * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] | 3849252726Srpaulo * Key[5..32] 3850252726Srpaulo */ 3851252726Srpaulo *pos++ = WNM_SLEEP_SUBELEM_GTK; 3852252726Srpaulo *pos++ = 11 + gsm->GTK_len; 3853252726Srpaulo /* Key ID in B0-B1 of Key Info */ 3854252726Srpaulo WPA_PUT_LE16(pos, gsm->GN & 0x03); 3855252726Srpaulo pos += 2; 3856252726Srpaulo *pos++ = gsm->GTK_len; 3857252726Srpaulo if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, pos) != 0) 3858252726Srpaulo return 0; 3859252726Srpaulo pos += 8; 3860252726Srpaulo os_memcpy(pos, gsm->GTK[gsm->GN - 1], gsm->GTK_len); 3861252726Srpaulo pos += gsm->GTK_len; 3862252726Srpaulo 3863252726Srpaulo wpa_printf(MSG_DEBUG, "WNM: GTK Key ID %u in WNM-Sleep Mode exit", 3864252726Srpaulo gsm->GN); 3865252726Srpaulo wpa_hexdump_key(MSG_DEBUG, "WNM: GTK in WNM-Sleep Mode exit", 3866252726Srpaulo gsm->GTK[gsm->GN - 1], gsm->GTK_len); 3867252726Srpaulo 3868252726Srpaulo return pos - start; 3869252726Srpaulo} 3870252726Srpaulo 3871252726Srpaulo 3872252726Srpaulo#ifdef CONFIG_IEEE80211W 3873252726Srpauloint wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos) 3874252726Srpaulo{ 3875252726Srpaulo struct wpa_group *gsm = sm->group; 3876252726Srpaulo u8 *start = pos; 3877281806Srpaulo size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); 3878252726Srpaulo 3879252726Srpaulo /* 3880252726Srpaulo * IGTK subelement: 3881252726Srpaulo * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16] 3882252726Srpaulo */ 3883252726Srpaulo *pos++ = WNM_SLEEP_SUBELEM_IGTK; 3884281806Srpaulo *pos++ = 2 + 6 + len; 3885252726Srpaulo WPA_PUT_LE16(pos, gsm->GN_igtk); 3886252726Srpaulo pos += 2; 3887252726Srpaulo if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos) != 0) 3888252726Srpaulo return 0; 3889252726Srpaulo pos += 6; 3890252726Srpaulo 3891281806Srpaulo os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], len); 3892281806Srpaulo pos += len; 3893252726Srpaulo 3894252726Srpaulo wpa_printf(MSG_DEBUG, "WNM: IGTK Key ID %u in WNM-Sleep Mode exit", 3895252726Srpaulo gsm->GN_igtk); 3896252726Srpaulo wpa_hexdump_key(MSG_DEBUG, "WNM: IGTK in WNM-Sleep Mode exit", 3897281806Srpaulo gsm->IGTK[gsm->GN_igtk - 4], len); 3898252726Srpaulo 3899252726Srpaulo return pos - start; 3900252726Srpaulo} 3901252726Srpaulo#endif /* CONFIG_IEEE80211W */ 3902346981Scy#endif /* CONFIG_WNM_AP */ 3903252726Srpaulo 3904252726Srpaulo 3905214501Srpaulostatic void wpa_group_setkeys(struct wpa_authenticator *wpa_auth, 3906214501Srpaulo struct wpa_group *group) 3907214501Srpaulo{ 3908214501Srpaulo int tmp; 3909214501Srpaulo 3910214501Srpaulo wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " 3911214501Srpaulo "SETKEYS (VLAN-ID %d)", group->vlan_id); 3912214501Srpaulo group->changed = TRUE; 3913214501Srpaulo group->wpa_group_state = WPA_GROUP_SETKEYS; 3914214501Srpaulo group->GTKReKey = FALSE; 3915214501Srpaulo tmp = group->GM; 3916214501Srpaulo group->GM = group->GN; 3917214501Srpaulo group->GN = tmp; 3918214501Srpaulo#ifdef CONFIG_IEEE80211W 3919214501Srpaulo tmp = group->GM_igtk; 3920214501Srpaulo group->GM_igtk = group->GN_igtk; 3921214501Srpaulo group->GN_igtk = tmp; 3922214501Srpaulo#endif /* CONFIG_IEEE80211W */ 3923214501Srpaulo /* "GKeyDoneStations = GNoStations" is done in more robust way by 3924214501Srpaulo * counting the STAs that are marked with GUpdateStationKeys instead of 3925214501Srpaulo * including all STAs that could be in not-yet-completed state. */ 3926214501Srpaulo wpa_gtk_update(wpa_auth, group); 3927214501Srpaulo 3928252726Srpaulo if (group->GKeyDoneStations) { 3929252726Srpaulo wpa_printf(MSG_DEBUG, "wpa_group_setkeys: Unexpected " 3930252726Srpaulo "GKeyDoneStations=%d when starting new GTK rekey", 3931252726Srpaulo group->GKeyDoneStations); 3932252726Srpaulo group->GKeyDoneStations = 0; 3933252726Srpaulo } 3934252726Srpaulo wpa_auth_for_each_sta(wpa_auth, wpa_group_update_sta, group); 3935214501Srpaulo wpa_printf(MSG_DEBUG, "wpa_group_setkeys: GKeyDoneStations=%d", 3936214501Srpaulo group->GKeyDoneStations); 3937214501Srpaulo} 3938214501Srpaulo 3939214501Srpaulo 3940252726Srpaulostatic int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth, 3941252726Srpaulo struct wpa_group *group) 3942214501Srpaulo{ 3943252726Srpaulo int ret = 0; 3944252726Srpaulo 3945252726Srpaulo if (wpa_auth_set_key(wpa_auth, group->vlan_id, 3946252726Srpaulo wpa_cipher_to_alg(wpa_auth->conf.wpa_group), 3947252726Srpaulo broadcast_ether_addr, group->GN, 3948252726Srpaulo group->GTK[group->GN - 1], group->GTK_len) < 0) 3949252726Srpaulo ret = -1; 3950252726Srpaulo 3951252726Srpaulo#ifdef CONFIG_IEEE80211W 3952281806Srpaulo if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) { 3953281806Srpaulo enum wpa_alg alg; 3954281806Srpaulo size_t len; 3955281806Srpaulo 3956281806Srpaulo alg = wpa_cipher_to_alg(wpa_auth->conf.group_mgmt_cipher); 3957281806Srpaulo len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher); 3958281806Srpaulo 3959281806Srpaulo if (ret == 0 && 3960281806Srpaulo wpa_auth_set_key(wpa_auth, group->vlan_id, alg, 3961281806Srpaulo broadcast_ether_addr, group->GN_igtk, 3962281806Srpaulo group->IGTK[group->GN_igtk - 4], len) < 0) 3963281806Srpaulo ret = -1; 3964281806Srpaulo } 3965252726Srpaulo#endif /* CONFIG_IEEE80211W */ 3966252726Srpaulo 3967252726Srpaulo return ret; 3968252726Srpaulo} 3969252726Srpaulo 3970252726Srpaulo 3971281806Srpaulostatic int wpa_group_disconnect_cb(struct wpa_state_machine *sm, void *ctx) 3972281806Srpaulo{ 3973281806Srpaulo if (sm->group == ctx) { 3974281806Srpaulo wpa_printf(MSG_DEBUG, "WPA: Mark STA " MACSTR 3975281806Srpaulo " for discconnection due to fatal failure", 3976281806Srpaulo MAC2STR(sm->addr)); 3977281806Srpaulo sm->Disconnect = TRUE; 3978281806Srpaulo } 3979281806Srpaulo 3980281806Srpaulo return 0; 3981281806Srpaulo} 3982281806Srpaulo 3983281806Srpaulo 3984281806Srpaulostatic void wpa_group_fatal_failure(struct wpa_authenticator *wpa_auth, 3985281806Srpaulo struct wpa_group *group) 3986281806Srpaulo{ 3987281806Srpaulo wpa_printf(MSG_DEBUG, "WPA: group state machine entering state FATAL_FAILURE"); 3988281806Srpaulo group->changed = TRUE; 3989281806Srpaulo group->wpa_group_state = WPA_GROUP_FATAL_FAILURE; 3990281806Srpaulo wpa_auth_for_each_sta(wpa_auth, wpa_group_disconnect_cb, group); 3991281806Srpaulo} 3992281806Srpaulo 3993281806Srpaulo 3994252726Srpaulostatic int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth, 3995252726Srpaulo struct wpa_group *group) 3996252726Srpaulo{ 3997214501Srpaulo wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " 3998214501Srpaulo "SETKEYSDONE (VLAN-ID %d)", group->vlan_id); 3999214501Srpaulo group->changed = TRUE; 4000214501Srpaulo group->wpa_group_state = WPA_GROUP_SETKEYSDONE; 4001214501Srpaulo 4002281806Srpaulo if (wpa_group_config_group_keys(wpa_auth, group) < 0) { 4003281806Srpaulo wpa_group_fatal_failure(wpa_auth, group); 4004252726Srpaulo return -1; 4005281806Srpaulo } 4006252726Srpaulo 4007252726Srpaulo return 0; 4008214501Srpaulo} 4009214501Srpaulo 4010214501Srpaulo 4011214501Srpaulostatic void wpa_group_sm_step(struct wpa_authenticator *wpa_auth, 4012214501Srpaulo struct wpa_group *group) 4013214501Srpaulo{ 4014214501Srpaulo if (group->GInit) { 4015214501Srpaulo wpa_group_gtk_init(wpa_auth, group); 4016281806Srpaulo } else if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) { 4017281806Srpaulo /* Do not allow group operations */ 4018214501Srpaulo } else if (group->wpa_group_state == WPA_GROUP_GTK_INIT && 4019214501Srpaulo group->GTKAuthenticator) { 4020214501Srpaulo wpa_group_setkeysdone(wpa_auth, group); 4021214501Srpaulo } else if (group->wpa_group_state == WPA_GROUP_SETKEYSDONE && 4022214501Srpaulo group->GTKReKey) { 4023214501Srpaulo wpa_group_setkeys(wpa_auth, group); 4024214501Srpaulo } else if (group->wpa_group_state == WPA_GROUP_SETKEYS) { 4025214501Srpaulo if (group->GKeyDoneStations == 0) 4026214501Srpaulo wpa_group_setkeysdone(wpa_auth, group); 4027214501Srpaulo else if (group->GTKReKey) 4028214501Srpaulo wpa_group_setkeys(wpa_auth, group); 4029214501Srpaulo } 4030214501Srpaulo} 4031214501Srpaulo 4032214501Srpaulo 4033214501Srpaulostatic int wpa_sm_step(struct wpa_state_machine *sm) 4034214501Srpaulo{ 4035214501Srpaulo if (sm == NULL) 4036214501Srpaulo return 0; 4037214501Srpaulo 4038214501Srpaulo if (sm->in_step_loop) { 4039214501Srpaulo /* This should not happen, but if it does, make sure we do not 4040214501Srpaulo * end up freeing the state machine too early by exiting the 4041214501Srpaulo * recursive call. */ 4042214501Srpaulo wpa_printf(MSG_ERROR, "WPA: wpa_sm_step() called recursively"); 4043214501Srpaulo return 0; 4044214501Srpaulo } 4045214501Srpaulo 4046214501Srpaulo sm->in_step_loop = 1; 4047214501Srpaulo do { 4048214501Srpaulo if (sm->pending_deinit) 4049214501Srpaulo break; 4050214501Srpaulo 4051214501Srpaulo sm->changed = FALSE; 4052214501Srpaulo sm->wpa_auth->group->changed = FALSE; 4053214501Srpaulo 4054214501Srpaulo SM_STEP_RUN(WPA_PTK); 4055214501Srpaulo if (sm->pending_deinit) 4056214501Srpaulo break; 4057214501Srpaulo SM_STEP_RUN(WPA_PTK_GROUP); 4058214501Srpaulo if (sm->pending_deinit) 4059214501Srpaulo break; 4060214501Srpaulo wpa_group_sm_step(sm->wpa_auth, sm->group); 4061214501Srpaulo } while (sm->changed || sm->wpa_auth->group->changed); 4062214501Srpaulo sm->in_step_loop = 0; 4063214501Srpaulo 4064214501Srpaulo if (sm->pending_deinit) { 4065214501Srpaulo wpa_printf(MSG_DEBUG, "WPA: Completing pending STA state " 4066214501Srpaulo "machine deinit for " MACSTR, MAC2STR(sm->addr)); 4067214501Srpaulo wpa_free_sta_sm(sm); 4068214501Srpaulo return 1; 4069214501Srpaulo } 4070214501Srpaulo return 0; 4071214501Srpaulo} 4072214501Srpaulo 4073214501Srpaulo 4074214501Srpaulostatic void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx) 4075214501Srpaulo{ 4076214501Srpaulo struct wpa_state_machine *sm = eloop_ctx; 4077214501Srpaulo wpa_sm_step(sm); 4078214501Srpaulo} 4079214501Srpaulo 4080214501Srpaulo 4081214501Srpaulovoid wpa_auth_sm_notify(struct wpa_state_machine *sm) 4082214501Srpaulo{ 4083214501Srpaulo if (sm == NULL) 4084214501Srpaulo return; 4085214501Srpaulo eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL); 4086214501Srpaulo} 4087214501Srpaulo 4088214501Srpaulo 4089214501Srpaulovoid wpa_gtk_rekey(struct wpa_authenticator *wpa_auth) 4090214501Srpaulo{ 4091214501Srpaulo int tmp, i; 4092214501Srpaulo struct wpa_group *group; 4093214501Srpaulo 4094214501Srpaulo if (wpa_auth == NULL) 4095214501Srpaulo return; 4096214501Srpaulo 4097214501Srpaulo group = wpa_auth->group; 4098214501Srpaulo 4099214501Srpaulo for (i = 0; i < 2; i++) { 4100214501Srpaulo tmp = group->GM; 4101214501Srpaulo group->GM = group->GN; 4102214501Srpaulo group->GN = tmp; 4103214501Srpaulo#ifdef CONFIG_IEEE80211W 4104214501Srpaulo tmp = group->GM_igtk; 4105214501Srpaulo group->GM_igtk = group->GN_igtk; 4106214501Srpaulo group->GN_igtk = tmp; 4107214501Srpaulo#endif /* CONFIG_IEEE80211W */ 4108214501Srpaulo wpa_gtk_update(wpa_auth, group); 4109252726Srpaulo wpa_group_config_group_keys(wpa_auth, group); 4110214501Srpaulo } 4111214501Srpaulo} 4112214501Srpaulo 4113214501Srpaulo 4114289549Srpaulostatic const char * wpa_bool_txt(int val) 4115214501Srpaulo{ 4116289549Srpaulo return val ? "TRUE" : "FALSE"; 4117214501Srpaulo} 4118214501Srpaulo 4119214501Srpaulo 4120214501Srpaulo#define RSN_SUITE "%02x-%02x-%02x-%d" 4121214501Srpaulo#define RSN_SUITE_ARG(s) \ 4122214501Srpaulo((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff 4123214501Srpaulo 4124214501Srpauloint wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen) 4125214501Srpaulo{ 4126214501Srpaulo int len = 0, ret; 4127214501Srpaulo char pmkid_txt[PMKID_LEN * 2 + 1]; 4128252726Srpaulo#ifdef CONFIG_RSN_PREAUTH 4129252726Srpaulo const int preauth = 1; 4130252726Srpaulo#else /* CONFIG_RSN_PREAUTH */ 4131252726Srpaulo const int preauth = 0; 4132252726Srpaulo#endif /* CONFIG_RSN_PREAUTH */ 4133214501Srpaulo 4134214501Srpaulo if (wpa_auth == NULL) 4135214501Srpaulo return len; 4136214501Srpaulo 4137214501Srpaulo ret = os_snprintf(buf + len, buflen - len, 4138214501Srpaulo "dot11RSNAOptionImplemented=TRUE\n" 4139252726Srpaulo "dot11RSNAPreauthenticationImplemented=%s\n" 4140214501Srpaulo "dot11RSNAEnabled=%s\n" 4141214501Srpaulo "dot11RSNAPreauthenticationEnabled=%s\n", 4142252726Srpaulo wpa_bool_txt(preauth), 4143214501Srpaulo wpa_bool_txt(wpa_auth->conf.wpa & WPA_PROTO_RSN), 4144214501Srpaulo wpa_bool_txt(wpa_auth->conf.rsn_preauth)); 4145281806Srpaulo if (os_snprintf_error(buflen - len, ret)) 4146214501Srpaulo return len; 4147214501Srpaulo len += ret; 4148214501Srpaulo 4149214501Srpaulo wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt), 4150214501Srpaulo wpa_auth->dot11RSNAPMKIDUsed, PMKID_LEN); 4151214501Srpaulo 4152214501Srpaulo ret = os_snprintf( 4153214501Srpaulo buf + len, buflen - len, 4154214501Srpaulo "dot11RSNAConfigVersion=%u\n" 4155214501Srpaulo "dot11RSNAConfigPairwiseKeysSupported=9999\n" 4156214501Srpaulo /* FIX: dot11RSNAConfigGroupCipher */ 4157214501Srpaulo /* FIX: dot11RSNAConfigGroupRekeyMethod */ 4158214501Srpaulo /* FIX: dot11RSNAConfigGroupRekeyTime */ 4159214501Srpaulo /* FIX: dot11RSNAConfigGroupRekeyPackets */ 4160214501Srpaulo "dot11RSNAConfigGroupRekeyStrict=%u\n" 4161214501Srpaulo "dot11RSNAConfigGroupUpdateCount=%u\n" 4162214501Srpaulo "dot11RSNAConfigPairwiseUpdateCount=%u\n" 4163214501Srpaulo "dot11RSNAConfigGroupCipherSize=%u\n" 4164214501Srpaulo "dot11RSNAConfigPMKLifetime=%u\n" 4165214501Srpaulo "dot11RSNAConfigPMKReauthThreshold=%u\n" 4166214501Srpaulo "dot11RSNAConfigNumberOfPTKSAReplayCounters=0\n" 4167214501Srpaulo "dot11RSNAConfigSATimeout=%u\n" 4168214501Srpaulo "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n" 4169214501Srpaulo "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n" 4170214501Srpaulo "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n" 4171214501Srpaulo "dot11RSNAPMKIDUsed=%s\n" 4172214501Srpaulo "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n" 4173214501Srpaulo "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n" 4174214501Srpaulo "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n" 4175214501Srpaulo "dot11RSNATKIPCounterMeasuresInvoked=%u\n" 4176214501Srpaulo "dot11RSNA4WayHandshakeFailures=%u\n" 4177214501Srpaulo "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n", 4178214501Srpaulo RSN_VERSION, 4179214501Srpaulo !!wpa_auth->conf.wpa_strict_rekey, 4180346981Scy wpa_auth->conf.wpa_group_update_count, 4181346981Scy wpa_auth->conf.wpa_pairwise_update_count, 4182252726Srpaulo wpa_cipher_key_len(wpa_auth->conf.wpa_group) * 8, 4183214501Srpaulo dot11RSNAConfigPMKLifetime, 4184214501Srpaulo dot11RSNAConfigPMKReauthThreshold, 4185214501Srpaulo dot11RSNAConfigSATimeout, 4186214501Srpaulo RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteSelected), 4187214501Srpaulo RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherSelected), 4188214501Srpaulo RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherSelected), 4189214501Srpaulo pmkid_txt, 4190214501Srpaulo RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteRequested), 4191214501Srpaulo RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherRequested), 4192214501Srpaulo RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherRequested), 4193214501Srpaulo wpa_auth->dot11RSNATKIPCounterMeasuresInvoked, 4194214501Srpaulo wpa_auth->dot11RSNA4WayHandshakeFailures); 4195281806Srpaulo if (os_snprintf_error(buflen - len, ret)) 4196214501Srpaulo return len; 4197214501Srpaulo len += ret; 4198214501Srpaulo 4199214501Srpaulo /* TODO: dot11RSNAConfigPairwiseCiphersTable */ 4200214501Srpaulo /* TODO: dot11RSNAConfigAuthenticationSuitesTable */ 4201214501Srpaulo 4202214501Srpaulo /* Private MIB */ 4203214501Srpaulo ret = os_snprintf(buf + len, buflen - len, "hostapdWPAGroupState=%d\n", 4204214501Srpaulo wpa_auth->group->wpa_group_state); 4205281806Srpaulo if (os_snprintf_error(buflen - len, ret)) 4206214501Srpaulo return len; 4207214501Srpaulo len += ret; 4208214501Srpaulo 4209214501Srpaulo return len; 4210214501Srpaulo} 4211214501Srpaulo 4212214501Srpaulo 4213214501Srpauloint wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen) 4214214501Srpaulo{ 4215214501Srpaulo int len = 0, ret; 4216214501Srpaulo u32 pairwise = 0; 4217214501Srpaulo 4218214501Srpaulo if (sm == NULL) 4219214501Srpaulo return 0; 4220214501Srpaulo 4221214501Srpaulo /* TODO: FF-FF-FF-FF-FF-FF entry for broadcast/multicast stats */ 4222214501Srpaulo 4223214501Srpaulo /* dot11RSNAStatsEntry */ 4224214501Srpaulo 4225252726Srpaulo pairwise = wpa_cipher_to_suite(sm->wpa == WPA_VERSION_WPA2 ? 4226252726Srpaulo WPA_PROTO_RSN : WPA_PROTO_WPA, 4227252726Srpaulo sm->pairwise); 4228252726Srpaulo if (pairwise == 0) 4229214501Srpaulo return 0; 4230214501Srpaulo 4231214501Srpaulo ret = os_snprintf( 4232214501Srpaulo buf + len, buflen - len, 4233214501Srpaulo /* TODO: dot11RSNAStatsIndex */ 4234214501Srpaulo "dot11RSNAStatsSTAAddress=" MACSTR "\n" 4235214501Srpaulo "dot11RSNAStatsVersion=1\n" 4236214501Srpaulo "dot11RSNAStatsSelectedPairwiseCipher=" RSN_SUITE "\n" 4237214501Srpaulo /* TODO: dot11RSNAStatsTKIPICVErrors */ 4238214501Srpaulo "dot11RSNAStatsTKIPLocalMICFailures=%u\n" 4239252726Srpaulo "dot11RSNAStatsTKIPRemoteMICFailures=%u\n" 4240214501Srpaulo /* TODO: dot11RSNAStatsCCMPReplays */ 4241214501Srpaulo /* TODO: dot11RSNAStatsCCMPDecryptErrors */ 4242214501Srpaulo /* TODO: dot11RSNAStatsTKIPReplays */, 4243214501Srpaulo MAC2STR(sm->addr), 4244214501Srpaulo RSN_SUITE_ARG(pairwise), 4245214501Srpaulo sm->dot11RSNAStatsTKIPLocalMICFailures, 4246214501Srpaulo sm->dot11RSNAStatsTKIPRemoteMICFailures); 4247281806Srpaulo if (os_snprintf_error(buflen - len, ret)) 4248214501Srpaulo return len; 4249214501Srpaulo len += ret; 4250214501Srpaulo 4251214501Srpaulo /* Private MIB */ 4252214501Srpaulo ret = os_snprintf(buf + len, buflen - len, 4253351611Scy "wpa=%d\n" 4254351611Scy "AKMSuiteSelector=" RSN_SUITE "\n" 4255214501Srpaulo "hostapdWPAPTKState=%d\n" 4256214501Srpaulo "hostapdWPAPTKGroupState=%d\n", 4257351611Scy sm->wpa, 4258351611Scy RSN_SUITE_ARG(wpa_akm_to_suite(sm->wpa_key_mgmt)), 4259214501Srpaulo sm->wpa_ptk_state, 4260214501Srpaulo sm->wpa_ptk_group_state); 4261281806Srpaulo if (os_snprintf_error(buflen - len, ret)) 4262214501Srpaulo return len; 4263214501Srpaulo len += ret; 4264214501Srpaulo 4265214501Srpaulo return len; 4266214501Srpaulo} 4267214501Srpaulo 4268214501Srpaulo 4269214501Srpaulovoid wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth) 4270214501Srpaulo{ 4271214501Srpaulo if (wpa_auth) 4272214501Srpaulo wpa_auth->dot11RSNATKIPCounterMeasuresInvoked++; 4273214501Srpaulo} 4274214501Srpaulo 4275214501Srpaulo 4276214501Srpauloint wpa_auth_pairwise_set(struct wpa_state_machine *sm) 4277214501Srpaulo{ 4278214501Srpaulo return sm && sm->pairwise_set; 4279214501Srpaulo} 4280214501Srpaulo 4281214501Srpaulo 4282214501Srpauloint wpa_auth_get_pairwise(struct wpa_state_machine *sm) 4283214501Srpaulo{ 4284214501Srpaulo return sm->pairwise; 4285214501Srpaulo} 4286214501Srpaulo 4287214501Srpaulo 4288346981Scyconst u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len) 4289346981Scy{ 4290346981Scy if (!sm) 4291346981Scy return NULL; 4292346981Scy *len = sm->pmk_len; 4293346981Scy return sm->PMK; 4294346981Scy} 4295346981Scy 4296346981Scy 4297214501Srpauloint wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm) 4298214501Srpaulo{ 4299214501Srpaulo if (sm == NULL) 4300214501Srpaulo return -1; 4301214501Srpaulo return sm->wpa_key_mgmt; 4302214501Srpaulo} 4303214501Srpaulo 4304214501Srpaulo 4305214501Srpauloint wpa_auth_sta_wpa_version(struct wpa_state_machine *sm) 4306214501Srpaulo{ 4307214501Srpaulo if (sm == NULL) 4308214501Srpaulo return 0; 4309214501Srpaulo return sm->wpa; 4310214501Srpaulo} 4311214501Srpaulo 4312214501Srpaulo 4313324697Sgordonint wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm) 4314324697Sgordon{ 4315324697Sgordon if (!sm || !wpa_key_mgmt_ft(sm->wpa_key_mgmt)) 4316324697Sgordon return 0; 4317324697Sgordon return sm->tk_already_set; 4318324697Sgordon} 4319324697Sgordon 4320324697Sgordon 4321346981Scyint wpa_auth_sta_fils_tk_already_set(struct wpa_state_machine *sm) 4322346981Scy{ 4323346981Scy if (!sm || !wpa_key_mgmt_fils(sm->wpa_key_mgmt)) 4324346981Scy return 0; 4325346981Scy return sm->tk_already_set; 4326346981Scy} 4327346981Scy 4328346981Scy 4329214501Srpauloint wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm, 4330214501Srpaulo struct rsn_pmksa_cache_entry *entry) 4331214501Srpaulo{ 4332214501Srpaulo if (sm == NULL || sm->pmksa != entry) 4333214501Srpaulo return -1; 4334214501Srpaulo sm->pmksa = NULL; 4335214501Srpaulo return 0; 4336214501Srpaulo} 4337214501Srpaulo 4338214501Srpaulo 4339214501Srpaulostruct rsn_pmksa_cache_entry * 4340214501Srpaulowpa_auth_sta_get_pmksa(struct wpa_state_machine *sm) 4341214501Srpaulo{ 4342214501Srpaulo return sm ? sm->pmksa : NULL; 4343214501Srpaulo} 4344214501Srpaulo 4345214501Srpaulo 4346214501Srpaulovoid wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm) 4347214501Srpaulo{ 4348214501Srpaulo if (sm) 4349214501Srpaulo sm->dot11RSNAStatsTKIPLocalMICFailures++; 4350214501Srpaulo} 4351214501Srpaulo 4352214501Srpaulo 4353214501Srpauloconst u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, size_t *len) 4354214501Srpaulo{ 4355214501Srpaulo if (wpa_auth == NULL) 4356214501Srpaulo return NULL; 4357214501Srpaulo *len = wpa_auth->wpa_ie_len; 4358214501Srpaulo return wpa_auth->wpa_ie; 4359214501Srpaulo} 4360214501Srpaulo 4361214501Srpaulo 4362214501Srpauloint wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk, 4363337817Scy unsigned int pmk_len, 4364214501Srpaulo int session_timeout, struct eapol_state_machine *eapol) 4365214501Srpaulo{ 4366252726Srpaulo if (sm == NULL || sm->wpa != WPA_VERSION_WPA2 || 4367252726Srpaulo sm->wpa_auth->conf.disable_pmksa_caching) 4368214501Srpaulo return -1; 4369214501Srpaulo 4370351611Scy#ifdef CONFIG_IEEE80211R_AP 4371351611Scy if (pmk_len >= 2 * PMK_LEN && wpa_key_mgmt_ft(sm->wpa_key_mgmt) && 4372351611Scy wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) && 4373351611Scy !wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) { 4374351611Scy /* Cache MPMK/XXKey instead of initial part from MSK */ 4375351611Scy pmk = pmk + PMK_LEN; 4376351611Scy pmk_len = PMK_LEN; 4377351611Scy } else 4378351611Scy#endif /* CONFIG_IEEE80211R_AP */ 4379346981Scy if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) { 4380337817Scy if (pmk_len > PMK_LEN_SUITE_B_192) 4381337817Scy pmk_len = PMK_LEN_SUITE_B_192; 4382337817Scy } else if (pmk_len > PMK_LEN) { 4383337817Scy pmk_len = PMK_LEN; 4384337817Scy } 4385337817Scy 4386351611Scy wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK", pmk, pmk_len); 4387337817Scy if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, pmk_len, NULL, 4388281806Srpaulo sm->PTK.kck, sm->PTK.kck_len, 4389214501Srpaulo sm->wpa_auth->addr, sm->addr, session_timeout, 4390214501Srpaulo eapol, sm->wpa_key_mgmt)) 4391214501Srpaulo return 0; 4392214501Srpaulo 4393214501Srpaulo return -1; 4394214501Srpaulo} 4395214501Srpaulo 4396214501Srpaulo 4397214501Srpauloint wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth, 4398214501Srpaulo const u8 *pmk, size_t len, const u8 *sta_addr, 4399214501Srpaulo int session_timeout, 4400214501Srpaulo struct eapol_state_machine *eapol) 4401214501Srpaulo{ 4402214501Srpaulo if (wpa_auth == NULL) 4403214501Srpaulo return -1; 4404214501Srpaulo 4405351611Scy wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from preauth", pmk, len); 4406337817Scy if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, len, NULL, 4407281806Srpaulo NULL, 0, 4408281806Srpaulo wpa_auth->addr, 4409214501Srpaulo sta_addr, session_timeout, eapol, 4410214501Srpaulo WPA_KEY_MGMT_IEEE8021X)) 4411214501Srpaulo return 0; 4412214501Srpaulo 4413214501Srpaulo return -1; 4414214501Srpaulo} 4415214501Srpaulo 4416214501Srpaulo 4417281806Srpauloint wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr, 4418337817Scy const u8 *pmk, const u8 *pmkid) 4419281806Srpaulo{ 4420281806Srpaulo if (wpa_auth->conf.disable_pmksa_caching) 4421281806Srpaulo return -1; 4422281806Srpaulo 4423351611Scy wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from SAE", pmk, PMK_LEN); 4424337817Scy if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, PMK_LEN, pmkid, 4425281806Srpaulo NULL, 0, 4426281806Srpaulo wpa_auth->addr, addr, 0, NULL, 4427281806Srpaulo WPA_KEY_MGMT_SAE)) 4428281806Srpaulo return 0; 4429281806Srpaulo 4430281806Srpaulo return -1; 4431281806Srpaulo} 4432281806Srpaulo 4433281806Srpaulo 4434346981Scyvoid wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid) 4435346981Scy{ 4436346981Scy os_memcpy(sm->pmkid, pmkid, PMKID_LEN); 4437346981Scy sm->pmkid_set = 1; 4438346981Scy} 4439346981Scy 4440346981Scy 4441346981Scyint wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr, 4442346981Scy const u8 *pmk, size_t pmk_len, const u8 *pmkid, 4443346981Scy int session_timeout, int akmp) 4444346981Scy{ 4445346981Scy if (wpa_auth->conf.disable_pmksa_caching) 4446346981Scy return -1; 4447346981Scy 4448351611Scy wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK (2)", pmk, PMK_LEN); 4449346981Scy if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, pmk_len, pmkid, 4450346981Scy NULL, 0, wpa_auth->addr, addr, session_timeout, 4451346981Scy NULL, akmp)) 4452346981Scy return 0; 4453346981Scy 4454346981Scy return -1; 4455346981Scy} 4456346981Scy 4457346981Scy 4458281806Srpaulovoid wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth, 4459281806Srpaulo const u8 *sta_addr) 4460281806Srpaulo{ 4461281806Srpaulo struct rsn_pmksa_cache_entry *pmksa; 4462281806Srpaulo 4463281806Srpaulo if (wpa_auth == NULL || wpa_auth->pmksa == NULL) 4464281806Srpaulo return; 4465281806Srpaulo pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, NULL); 4466281806Srpaulo if (pmksa) { 4467281806Srpaulo wpa_printf(MSG_DEBUG, "WPA: Remove PMKSA cache entry for " 4468281806Srpaulo MACSTR " based on request", MAC2STR(sta_addr)); 4469281806Srpaulo pmksa_cache_free_entry(wpa_auth->pmksa, pmksa); 4470281806Srpaulo } 4471281806Srpaulo} 4472281806Srpaulo 4473281806Srpaulo 4474337817Scyint wpa_auth_pmksa_list(struct wpa_authenticator *wpa_auth, char *buf, 4475337817Scy size_t len) 4476337817Scy{ 4477337817Scy if (!wpa_auth || !wpa_auth->pmksa) 4478337817Scy return 0; 4479337817Scy return pmksa_cache_auth_list(wpa_auth->pmksa, buf, len); 4480337817Scy} 4481337817Scy 4482337817Scy 4483337817Scyvoid wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth) 4484337817Scy{ 4485337817Scy if (wpa_auth && wpa_auth->pmksa) 4486337817Scy pmksa_cache_auth_flush(wpa_auth->pmksa); 4487337817Scy} 4488337817Scy 4489337817Scy 4490346981Scy#ifdef CONFIG_PMKSA_CACHE_EXTERNAL 4491346981Scy#ifdef CONFIG_MESH 4492346981Scy 4493346981Scyint wpa_auth_pmksa_list_mesh(struct wpa_authenticator *wpa_auth, const u8 *addr, 4494346981Scy char *buf, size_t len) 4495346981Scy{ 4496346981Scy if (!wpa_auth || !wpa_auth->pmksa) 4497346981Scy return 0; 4498346981Scy 4499346981Scy return pmksa_cache_auth_list_mesh(wpa_auth->pmksa, addr, buf, len); 4500346981Scy} 4501346981Scy 4502346981Scy 4503337817Scystruct rsn_pmksa_cache_entry * 4504346981Scywpa_auth_pmksa_create_entry(const u8 *aa, const u8 *spa, const u8 *pmk, 4505346981Scy const u8 *pmkid, int expiration) 4506337817Scy{ 4507346981Scy struct rsn_pmksa_cache_entry *entry; 4508346981Scy struct os_reltime now; 4509346981Scy 4510346981Scy entry = pmksa_cache_auth_create_entry(pmk, PMK_LEN, pmkid, NULL, 0, aa, 4511346981Scy spa, 0, NULL, WPA_KEY_MGMT_SAE); 4512346981Scy if (!entry) 4513346981Scy return NULL; 4514346981Scy 4515346981Scy os_get_reltime(&now); 4516346981Scy entry->expiration = now.sec + expiration; 4517346981Scy return entry; 4518346981Scy} 4519346981Scy 4520346981Scy 4521346981Scyint wpa_auth_pmksa_add_entry(struct wpa_authenticator *wpa_auth, 4522346981Scy struct rsn_pmksa_cache_entry *entry) 4523346981Scy{ 4524346981Scy int ret; 4525346981Scy 4526337817Scy if (!wpa_auth || !wpa_auth->pmksa) 4527346981Scy return -1; 4528346981Scy 4529346981Scy ret = pmksa_cache_auth_add_entry(wpa_auth->pmksa, entry); 4530346981Scy if (ret < 0) 4531346981Scy wpa_printf(MSG_DEBUG, 4532346981Scy "RSN: Failed to store external PMKSA cache for " 4533346981Scy MACSTR, MAC2STR(entry->spa)); 4534346981Scy 4535346981Scy return ret; 4536346981Scy} 4537346981Scy 4538346981Scy#endif /* CONFIG_MESH */ 4539346981Scy#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ 4540346981Scy 4541346981Scy 4542346981Scystruct rsn_pmksa_cache_entry * 4543346981Scywpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr, 4544346981Scy const u8 *pmkid) 4545346981Scy{ 4546346981Scy if (!wpa_auth || !wpa_auth->pmksa) 4547337817Scy return NULL; 4548346981Scy return pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, pmkid); 4549337817Scy} 4550337817Scy 4551337817Scy 4552337817Scyvoid wpa_auth_pmksa_set_to_sm(struct rsn_pmksa_cache_entry *pmksa, 4553337817Scy struct wpa_state_machine *sm, 4554337817Scy struct wpa_authenticator *wpa_auth, 4555337817Scy u8 *pmkid, u8 *pmk) 4556337817Scy{ 4557337817Scy if (!sm) 4558337817Scy return; 4559337817Scy 4560337817Scy sm->pmksa = pmksa; 4561337817Scy os_memcpy(pmk, pmksa->pmk, PMK_LEN); 4562337817Scy os_memcpy(pmkid, pmksa->pmkid, PMKID_LEN); 4563337817Scy os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmksa->pmkid, PMKID_LEN); 4564337817Scy} 4565337817Scy 4566337817Scy 4567289549Srpaulo/* 4568289549Srpaulo * Remove and free the group from wpa_authenticator. This is triggered by a 4569289549Srpaulo * callback to make sure nobody is currently iterating the group list while it 4570289549Srpaulo * gets modified. 4571289549Srpaulo */ 4572289549Srpaulostatic void wpa_group_free(struct wpa_authenticator *wpa_auth, 4573289549Srpaulo struct wpa_group *group) 4574289549Srpaulo{ 4575289549Srpaulo struct wpa_group *prev = wpa_auth->group; 4576289549Srpaulo 4577289549Srpaulo wpa_printf(MSG_DEBUG, "WPA: Remove group state machine for VLAN-ID %d", 4578289549Srpaulo group->vlan_id); 4579289549Srpaulo 4580289549Srpaulo while (prev) { 4581289549Srpaulo if (prev->next == group) { 4582289549Srpaulo /* This never frees the special first group as needed */ 4583289549Srpaulo prev->next = group->next; 4584289549Srpaulo os_free(group); 4585289549Srpaulo break; 4586289549Srpaulo } 4587289549Srpaulo prev = prev->next; 4588289549Srpaulo } 4589289549Srpaulo 4590289549Srpaulo} 4591289549Srpaulo 4592289549Srpaulo 4593289549Srpaulo/* Increase the reference counter for group */ 4594289549Srpaulostatic void wpa_group_get(struct wpa_authenticator *wpa_auth, 4595289549Srpaulo struct wpa_group *group) 4596289549Srpaulo{ 4597289549Srpaulo /* Skip the special first group */ 4598289549Srpaulo if (wpa_auth->group == group) 4599289549Srpaulo return; 4600289549Srpaulo 4601289549Srpaulo group->references++; 4602289549Srpaulo} 4603289549Srpaulo 4604289549Srpaulo 4605289549Srpaulo/* Decrease the reference counter and maybe free the group */ 4606289549Srpaulostatic void wpa_group_put(struct wpa_authenticator *wpa_auth, 4607289549Srpaulo struct wpa_group *group) 4608289549Srpaulo{ 4609289549Srpaulo /* Skip the special first group */ 4610289549Srpaulo if (wpa_auth->group == group) 4611289549Srpaulo return; 4612289549Srpaulo 4613289549Srpaulo group->references--; 4614289549Srpaulo if (group->references) 4615289549Srpaulo return; 4616289549Srpaulo wpa_group_free(wpa_auth, group); 4617289549Srpaulo} 4618289549Srpaulo 4619289549Srpaulo 4620289549Srpaulo/* 4621289549Srpaulo * Add a group that has its references counter set to zero. Caller needs to 4622289549Srpaulo * call wpa_group_get() on the return value to mark the entry in use. 4623289549Srpaulo */ 4624214501Srpaulostatic struct wpa_group * 4625214501Srpaulowpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id) 4626214501Srpaulo{ 4627214501Srpaulo struct wpa_group *group; 4628214501Srpaulo 4629214501Srpaulo if (wpa_auth == NULL || wpa_auth->group == NULL) 4630214501Srpaulo return NULL; 4631214501Srpaulo 4632214501Srpaulo wpa_printf(MSG_DEBUG, "WPA: Add group state machine for VLAN-ID %d", 4633214501Srpaulo vlan_id); 4634252726Srpaulo group = wpa_group_init(wpa_auth, vlan_id, 0); 4635214501Srpaulo if (group == NULL) 4636214501Srpaulo return NULL; 4637214501Srpaulo 4638214501Srpaulo group->next = wpa_auth->group->next; 4639214501Srpaulo wpa_auth->group->next = group; 4640214501Srpaulo 4641214501Srpaulo return group; 4642214501Srpaulo} 4643214501Srpaulo 4644214501Srpaulo 4645337817Scy/* 4646337817Scy * Enforce that the group state machine for the VLAN is running, increase 4647337817Scy * reference counter as interface is up. References might have been increased 4648337817Scy * even if a negative value is returned. 4649337817Scy * Returns: -1 on error (group missing, group already failed); otherwise, 0 4650337817Scy */ 4651337817Scyint wpa_auth_ensure_group(struct wpa_authenticator *wpa_auth, int vlan_id) 4652337817Scy{ 4653337817Scy struct wpa_group *group; 4654337817Scy 4655337817Scy if (wpa_auth == NULL) 4656337817Scy return 0; 4657337817Scy 4658337817Scy group = wpa_auth->group; 4659337817Scy while (group) { 4660337817Scy if (group->vlan_id == vlan_id) 4661337817Scy break; 4662337817Scy group = group->next; 4663337817Scy } 4664337817Scy 4665337817Scy if (group == NULL) { 4666337817Scy group = wpa_auth_add_group(wpa_auth, vlan_id); 4667337817Scy if (group == NULL) 4668337817Scy return -1; 4669337817Scy } 4670337817Scy 4671337817Scy wpa_printf(MSG_DEBUG, 4672337817Scy "WPA: Ensure group state machine running for VLAN ID %d", 4673337817Scy vlan_id); 4674337817Scy 4675337817Scy wpa_group_get(wpa_auth, group); 4676337817Scy group->num_setup_iface++; 4677337817Scy 4678337817Scy if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) 4679337817Scy return -1; 4680337817Scy 4681337817Scy return 0; 4682337817Scy} 4683337817Scy 4684337817Scy 4685337817Scy/* 4686337817Scy * Decrease reference counter, expected to be zero afterwards. 4687337817Scy * returns: -1 on error (group not found, group in fail state) 4688337817Scy * -2 if wpa_group is still referenced 4689337817Scy * 0 else 4690337817Scy */ 4691337817Scyint wpa_auth_release_group(struct wpa_authenticator *wpa_auth, int vlan_id) 4692337817Scy{ 4693337817Scy struct wpa_group *group; 4694337817Scy int ret = 0; 4695337817Scy 4696337817Scy if (wpa_auth == NULL) 4697337817Scy return 0; 4698337817Scy 4699337817Scy group = wpa_auth->group; 4700337817Scy while (group) { 4701337817Scy if (group->vlan_id == vlan_id) 4702337817Scy break; 4703337817Scy group = group->next; 4704337817Scy } 4705337817Scy 4706337817Scy if (group == NULL) 4707337817Scy return -1; 4708337817Scy 4709337817Scy wpa_printf(MSG_DEBUG, 4710337817Scy "WPA: Try stopping group state machine for VLAN ID %d", 4711337817Scy vlan_id); 4712337817Scy 4713337817Scy if (group->num_setup_iface <= 0) { 4714337817Scy wpa_printf(MSG_ERROR, 4715337817Scy "WPA: wpa_auth_release_group called more often than wpa_auth_ensure_group for VLAN ID %d, skipping.", 4716337817Scy vlan_id); 4717337817Scy return -1; 4718337817Scy } 4719337817Scy group->num_setup_iface--; 4720337817Scy 4721337817Scy if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) 4722337817Scy ret = -1; 4723337817Scy 4724337817Scy if (group->references > 1) { 4725337817Scy wpa_printf(MSG_DEBUG, 4726337817Scy "WPA: Cannot stop group state machine for VLAN ID %d as references are still hold", 4727337817Scy vlan_id); 4728337817Scy ret = -2; 4729337817Scy } 4730337817Scy 4731337817Scy wpa_group_put(wpa_auth, group); 4732337817Scy 4733337817Scy return ret; 4734337817Scy} 4735337817Scy 4736337817Scy 4737214501Srpauloint wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id) 4738214501Srpaulo{ 4739214501Srpaulo struct wpa_group *group; 4740214501Srpaulo 4741214501Srpaulo if (sm == NULL || sm->wpa_auth == NULL) 4742214501Srpaulo return 0; 4743214501Srpaulo 4744214501Srpaulo group = sm->wpa_auth->group; 4745214501Srpaulo while (group) { 4746214501Srpaulo if (group->vlan_id == vlan_id) 4747214501Srpaulo break; 4748214501Srpaulo group = group->next; 4749214501Srpaulo } 4750214501Srpaulo 4751214501Srpaulo if (group == NULL) { 4752214501Srpaulo group = wpa_auth_add_group(sm->wpa_auth, vlan_id); 4753214501Srpaulo if (group == NULL) 4754214501Srpaulo return -1; 4755214501Srpaulo } 4756214501Srpaulo 4757214501Srpaulo if (sm->group == group) 4758214501Srpaulo return 0; 4759214501Srpaulo 4760281806Srpaulo if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) 4761281806Srpaulo return -1; 4762281806Srpaulo 4763214501Srpaulo wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR " to use group state " 4764214501Srpaulo "machine for VLAN ID %d", MAC2STR(sm->addr), vlan_id); 4765214501Srpaulo 4766289549Srpaulo wpa_group_get(sm->wpa_auth, group); 4767289549Srpaulo wpa_group_put(sm->wpa_auth, sm->group); 4768214501Srpaulo sm->group = group; 4769289549Srpaulo 4770214501Srpaulo return 0; 4771214501Srpaulo} 4772252726Srpaulo 4773252726Srpaulo 4774252726Srpaulovoid wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth, 4775252726Srpaulo struct wpa_state_machine *sm, int ack) 4776252726Srpaulo{ 4777252726Srpaulo if (wpa_auth == NULL || sm == NULL) 4778252726Srpaulo return; 4779252726Srpaulo wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key TX status for STA " MACSTR 4780252726Srpaulo " ack=%d", MAC2STR(sm->addr), ack); 4781252726Srpaulo if (sm->pending_1_of_4_timeout && ack) { 4782252726Srpaulo /* 4783252726Srpaulo * Some deployed supplicant implementations update their SNonce 4784252726Srpaulo * for each EAPOL-Key 2/4 message even within the same 4-way 4785252726Srpaulo * handshake and then fail to use the first SNonce when 4786252726Srpaulo * deriving the PTK. This results in unsuccessful 4-way 4787252726Srpaulo * handshake whenever the relatively short initial timeout is 4788252726Srpaulo * reached and EAPOL-Key 1/4 is retransmitted. Try to work 4789252726Srpaulo * around this by increasing the timeout now that we know that 4790252726Srpaulo * the station has received the frame. 4791252726Srpaulo */ 4792252726Srpaulo int timeout_ms = eapol_key_timeout_subseq; 4793252726Srpaulo wpa_printf(MSG_DEBUG, "WPA: Increase initial EAPOL-Key 1/4 " 4794252726Srpaulo "timeout by %u ms because of acknowledged frame", 4795252726Srpaulo timeout_ms); 4796252726Srpaulo eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm); 4797252726Srpaulo eloop_register_timeout(timeout_ms / 1000, 4798252726Srpaulo (timeout_ms % 1000) * 1000, 4799252726Srpaulo wpa_send_eapol_timeout, wpa_auth, sm); 4800252726Srpaulo } 4801346981Scy 4802346981Scy#ifdef CONFIG_TESTING_OPTIONS 4803346981Scy if (sm->eapol_status_cb) { 4804346981Scy sm->eapol_status_cb(sm->eapol_status_cb_ctx1, 4805346981Scy sm->eapol_status_cb_ctx2); 4806346981Scy sm->eapol_status_cb = NULL; 4807346981Scy } 4808346981Scy#endif /* CONFIG_TESTING_OPTIONS */ 4809252726Srpaulo} 4810252726Srpaulo 4811252726Srpaulo 4812252726Srpauloint wpa_auth_uses_sae(struct wpa_state_machine *sm) 4813252726Srpaulo{ 4814252726Srpaulo if (sm == NULL) 4815252726Srpaulo return 0; 4816252726Srpaulo return wpa_key_mgmt_sae(sm->wpa_key_mgmt); 4817252726Srpaulo} 4818281806Srpaulo 4819281806Srpaulo 4820281806Srpauloint wpa_auth_uses_ft_sae(struct wpa_state_machine *sm) 4821281806Srpaulo{ 4822281806Srpaulo if (sm == NULL) 4823281806Srpaulo return 0; 4824281806Srpaulo return sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE; 4825281806Srpaulo} 4826281806Srpaulo 4827281806Srpaulo 4828281806Srpaulo#ifdef CONFIG_P2P 4829281806Srpauloint wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr) 4830281806Srpaulo{ 4831281806Srpaulo if (sm == NULL || WPA_GET_BE32(sm->ip_addr) == 0) 4832281806Srpaulo return -1; 4833281806Srpaulo os_memcpy(addr, sm->ip_addr, 4); 4834281806Srpaulo return 0; 4835281806Srpaulo} 4836281806Srpaulo#endif /* CONFIG_P2P */ 4837281806Srpaulo 4838281806Srpaulo 4839281806Srpauloint wpa_auth_radius_das_disconnect_pmksa(struct wpa_authenticator *wpa_auth, 4840281806Srpaulo struct radius_das_attrs *attr) 4841281806Srpaulo{ 4842281806Srpaulo return pmksa_cache_auth_radius_das_disconnect(wpa_auth->pmksa, attr); 4843281806Srpaulo} 4844281806Srpaulo 4845281806Srpaulo 4846281806Srpaulovoid wpa_auth_reconfig_group_keys(struct wpa_authenticator *wpa_auth) 4847281806Srpaulo{ 4848281806Srpaulo struct wpa_group *group; 4849281806Srpaulo 4850281806Srpaulo if (!wpa_auth) 4851281806Srpaulo return; 4852281806Srpaulo for (group = wpa_auth->group; group; group = group->next) 4853281806Srpaulo wpa_group_config_group_keys(wpa_auth, group); 4854281806Srpaulo} 4855346981Scy 4856346981Scy 4857346981Scy#ifdef CONFIG_FILS 4858346981Scy 4859346981Scystruct wpa_auth_fils_iter_data { 4860346981Scy struct wpa_authenticator *auth; 4861346981Scy const u8 *cache_id; 4862346981Scy struct rsn_pmksa_cache_entry *pmksa; 4863346981Scy const u8 *spa; 4864346981Scy const u8 *pmkid; 4865346981Scy}; 4866346981Scy 4867346981Scy 4868346981Scystatic int wpa_auth_fils_iter(struct wpa_authenticator *a, void *ctx) 4869346981Scy{ 4870346981Scy struct wpa_auth_fils_iter_data *data = ctx; 4871346981Scy 4872346981Scy if (a == data->auth || !a->conf.fils_cache_id_set || 4873346981Scy os_memcmp(a->conf.fils_cache_id, data->cache_id, 4874346981Scy FILS_CACHE_ID_LEN) != 0) 4875346981Scy return 0; 4876346981Scy data->pmksa = pmksa_cache_auth_get(a->pmksa, data->spa, data->pmkid); 4877346981Scy return data->pmksa != NULL; 4878346981Scy} 4879346981Scy 4880346981Scy 4881346981Scystruct rsn_pmksa_cache_entry * 4882346981Scywpa_auth_pmksa_get_fils_cache_id(struct wpa_authenticator *wpa_auth, 4883346981Scy const u8 *sta_addr, const u8 *pmkid) 4884346981Scy{ 4885346981Scy struct wpa_auth_fils_iter_data idata; 4886346981Scy 4887346981Scy if (!wpa_auth->conf.fils_cache_id_set) 4888346981Scy return NULL; 4889346981Scy idata.auth = wpa_auth; 4890346981Scy idata.cache_id = wpa_auth->conf.fils_cache_id; 4891346981Scy idata.pmksa = NULL; 4892346981Scy idata.spa = sta_addr; 4893346981Scy idata.pmkid = pmkid; 4894346981Scy wpa_auth_for_each_auth(wpa_auth, wpa_auth_fils_iter, &idata); 4895346981Scy return idata.pmksa; 4896346981Scy} 4897346981Scy 4898346981Scy 4899346981Scy#ifdef CONFIG_IEEE80211R_AP 4900346981Scyint wpa_auth_write_fte(struct wpa_authenticator *wpa_auth, int use_sha384, 4901346981Scy u8 *buf, size_t len) 4902346981Scy{ 4903346981Scy struct wpa_auth_config *conf = &wpa_auth->conf; 4904346981Scy 4905346981Scy return wpa_write_ftie(conf, use_sha384, conf->r0_key_holder, 4906346981Scy conf->r0_key_holder_len, 4907346981Scy NULL, NULL, buf, len, NULL, 0); 4908346981Scy} 4909346981Scy#endif /* CONFIG_IEEE80211R_AP */ 4910346981Scy 4911346981Scy 4912346981Scyvoid wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm, 4913346981Scy u8 *fils_anonce, u8 *fils_snonce, 4914346981Scy u8 *fils_kek, size_t *fils_kek_len) 4915346981Scy{ 4916346981Scy os_memcpy(fils_anonce, sm->ANonce, WPA_NONCE_LEN); 4917346981Scy os_memcpy(fils_snonce, sm->SNonce, WPA_NONCE_LEN); 4918346981Scy os_memcpy(fils_kek, sm->PTK.kek, WPA_KEK_MAX_LEN); 4919346981Scy *fils_kek_len = sm->PTK.kek_len; 4920346981Scy} 4921346981Scy 4922346981Scy 4923346981Scyvoid wpa_auth_add_fils_pmk_pmkid(struct wpa_state_machine *sm, const u8 *pmk, 4924346981Scy size_t pmk_len, const u8 *pmkid) 4925346981Scy{ 4926346981Scy os_memcpy(sm->PMK, pmk, pmk_len); 4927346981Scy sm->pmk_len = pmk_len; 4928346981Scy os_memcpy(sm->pmkid, pmkid, PMKID_LEN); 4929346981Scy sm->pmkid_set = 1; 4930346981Scy} 4931346981Scy 4932346981Scy#endif /* CONFIG_FILS */ 4933346981Scy 4934346981Scy 4935346981Scyvoid wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg) 4936346981Scy{ 4937346981Scy if (sm) 4938346981Scy sm->auth_alg = auth_alg; 4939346981Scy} 4940346981Scy 4941346981Scy 4942346981Scy#ifdef CONFIG_DPP2 4943346981Scyvoid wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z) 4944346981Scy{ 4945346981Scy if (sm) { 4946346981Scy wpabuf_clear_free(sm->dpp_z); 4947346981Scy sm->dpp_z = z ? wpabuf_dup(z) : NULL; 4948346981Scy } 4949346981Scy} 4950346981Scy#endif /* CONFIG_DPP2 */ 4951346981Scy 4952346981Scy 4953346981Scy#ifdef CONFIG_TESTING_OPTIONS 4954346981Scy 4955346981Scyint wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce, 4956346981Scy void (*cb)(void *ctx1, void *ctx2), 4957346981Scy void *ctx1, void *ctx2) 4958346981Scy{ 4959346981Scy const u8 *anonce = sm->ANonce; 4960346981Scy u8 anonce_buf[WPA_NONCE_LEN]; 4961346981Scy 4962346981Scy if (change_anonce) { 4963346981Scy if (random_get_bytes(anonce_buf, WPA_NONCE_LEN)) 4964346981Scy return -1; 4965346981Scy anonce = anonce_buf; 4966346981Scy } 4967346981Scy 4968346981Scy wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 4969346981Scy "sending 1/4 msg of 4-Way Handshake (TESTING)"); 4970346981Scy wpa_send_eapol(sm->wpa_auth, sm, 4971346981Scy WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL, 4972346981Scy anonce, NULL, 0, 0, 0); 4973346981Scy return 0; 4974346981Scy} 4975346981Scy 4976346981Scy 4977346981Scyint wpa_auth_resend_m3(struct wpa_state_machine *sm, 4978346981Scy void (*cb)(void *ctx1, void *ctx2), 4979346981Scy void *ctx1, void *ctx2) 4980346981Scy{ 4981346981Scy u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos; 4982346981Scy#ifdef CONFIG_IEEE80211W 4983346981Scy u8 *opos; 4984346981Scy#endif /* CONFIG_IEEE80211W */ 4985346981Scy size_t gtk_len, kde_len; 4986346981Scy struct wpa_group *gsm = sm->group; 4987346981Scy u8 *wpa_ie; 4988346981Scy int wpa_ie_len, secure, keyidx, encr = 0; 4989346981Scy 4990346981Scy /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE], 4991346981Scy GTK[GN], IGTK, [FTIE], [TIE * 2]) 4992346981Scy */ 4993346981Scy 4994346981Scy /* Use 0 RSC */ 4995346981Scy os_memset(rsc, 0, WPA_KEY_RSC_LEN); 4996346981Scy /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */ 4997346981Scy wpa_ie = sm->wpa_auth->wpa_ie; 4998346981Scy wpa_ie_len = sm->wpa_auth->wpa_ie_len; 4999346981Scy if (sm->wpa == WPA_VERSION_WPA && 5000346981Scy (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) && 5001346981Scy wpa_ie_len > wpa_ie[1] + 2 && wpa_ie[0] == WLAN_EID_RSN) { 5002346981Scy /* WPA-only STA, remove RSN IE and possible MDIE */ 5003346981Scy wpa_ie = wpa_ie + wpa_ie[1] + 2; 5004346981Scy if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN) 5005346981Scy wpa_ie = wpa_ie + wpa_ie[1] + 2; 5006346981Scy wpa_ie_len = wpa_ie[1] + 2; 5007346981Scy } 5008346981Scy wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 5009346981Scy "sending 3/4 msg of 4-Way Handshake (TESTING)"); 5010346981Scy if (sm->wpa == WPA_VERSION_WPA2) { 5011346981Scy /* WPA2 send GTK in the 4-way handshake */ 5012346981Scy secure = 1; 5013346981Scy gtk = gsm->GTK[gsm->GN - 1]; 5014346981Scy gtk_len = gsm->GTK_len; 5015346981Scy keyidx = gsm->GN; 5016346981Scy _rsc = rsc; 5017346981Scy encr = 1; 5018346981Scy } else { 5019346981Scy /* WPA does not include GTK in msg 3/4 */ 5020346981Scy secure = 0; 5021346981Scy gtk = NULL; 5022346981Scy gtk_len = 0; 5023346981Scy keyidx = 0; 5024346981Scy _rsc = NULL; 5025346981Scy if (sm->rx_eapol_key_secure) { 5026346981Scy /* 5027346981Scy * It looks like Windows 7 supplicant tries to use 5028346981Scy * Secure bit in msg 2/4 after having reported Michael 5029346981Scy * MIC failure and it then rejects the 4-way handshake 5030346981Scy * if msg 3/4 does not set Secure bit. Work around this 5031346981Scy * by setting the Secure bit here even in the case of 5032346981Scy * WPA if the supplicant used it first. 5033346981Scy */ 5034346981Scy wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 5035346981Scy "STA used Secure bit in WPA msg 2/4 - " 5036346981Scy "set Secure for 3/4 as workaround"); 5037346981Scy secure = 1; 5038346981Scy } 5039346981Scy } 5040346981Scy 5041346981Scy kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm); 5042346981Scy if (gtk) 5043346981Scy kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len; 5044346981Scy#ifdef CONFIG_IEEE80211R_AP 5045346981Scy if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { 5046346981Scy kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */ 5047346981Scy kde_len += 300; /* FTIE + 2 * TIE */ 5048346981Scy } 5049346981Scy#endif /* CONFIG_IEEE80211R_AP */ 5050346981Scy kde = os_malloc(kde_len); 5051346981Scy if (kde == NULL) 5052346981Scy return -1; 5053346981Scy 5054346981Scy pos = kde; 5055346981Scy os_memcpy(pos, wpa_ie, wpa_ie_len); 5056346981Scy pos += wpa_ie_len; 5057346981Scy#ifdef CONFIG_IEEE80211R_AP 5058346981Scy if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { 5059346981Scy int res; 5060346981Scy size_t elen; 5061346981Scy 5062346981Scy elen = pos - kde; 5063346981Scy res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name); 5064346981Scy if (res < 0) { 5065346981Scy wpa_printf(MSG_ERROR, "FT: Failed to insert " 5066346981Scy "PMKR1Name into RSN IE in EAPOL-Key data"); 5067346981Scy os_free(kde); 5068346981Scy return -1; 5069346981Scy } 5070346981Scy pos -= wpa_ie_len; 5071346981Scy pos += elen; 5072346981Scy } 5073346981Scy#endif /* CONFIG_IEEE80211R_AP */ 5074346981Scy if (gtk) { 5075346981Scy u8 hdr[2]; 5076346981Scy hdr[0] = keyidx & 0x03; 5077346981Scy hdr[1] = 0; 5078346981Scy pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, 5079346981Scy gtk, gtk_len); 5080346981Scy } 5081346981Scy#ifdef CONFIG_IEEE80211W 5082346981Scy opos = pos; 5083346981Scy pos = ieee80211w_kde_add(sm, pos); 5084346981Scy if (pos - opos >= 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN) { 5085346981Scy /* skip KDE header and keyid */ 5086346981Scy opos += 2 + RSN_SELECTOR_LEN + 2; 5087346981Scy os_memset(opos, 0, 6); /* clear PN */ 5088346981Scy } 5089346981Scy#endif /* CONFIG_IEEE80211W */ 5090346981Scy if (ocv_oci_add(sm, &pos) < 0) { 5091346981Scy os_free(kde); 5092346981Scy return -1; 5093346981Scy } 5094346981Scy 5095346981Scy#ifdef CONFIG_IEEE80211R_AP 5096346981Scy if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { 5097346981Scy int res; 5098346981Scy struct wpa_auth_config *conf; 5099346981Scy 5100346981Scy conf = &sm->wpa_auth->conf; 5101346981Scy if (sm->assoc_resp_ftie && 5102346981Scy kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) { 5103346981Scy os_memcpy(pos, sm->assoc_resp_ftie, 5104346981Scy 2 + sm->assoc_resp_ftie[1]); 5105346981Scy res = 2 + sm->assoc_resp_ftie[1]; 5106346981Scy } else { 5107346981Scy int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt); 5108346981Scy 5109346981Scy res = wpa_write_ftie(conf, use_sha384, 5110346981Scy conf->r0_key_holder, 5111346981Scy conf->r0_key_holder_len, 5112346981Scy NULL, NULL, pos, 5113346981Scy kde + kde_len - pos, 5114346981Scy NULL, 0); 5115346981Scy } 5116346981Scy if (res < 0) { 5117346981Scy wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE " 5118346981Scy "into EAPOL-Key Key Data"); 5119346981Scy os_free(kde); 5120346981Scy return -1; 5121346981Scy } 5122346981Scy pos += res; 5123346981Scy 5124346981Scy /* TIE[ReassociationDeadline] (TU) */ 5125346981Scy *pos++ = WLAN_EID_TIMEOUT_INTERVAL; 5126346981Scy *pos++ = 5; 5127346981Scy *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE; 5128346981Scy WPA_PUT_LE32(pos, conf->reassociation_deadline); 5129346981Scy pos += 4; 5130346981Scy 5131346981Scy /* TIE[KeyLifetime] (seconds) */ 5132346981Scy *pos++ = WLAN_EID_TIMEOUT_INTERVAL; 5133346981Scy *pos++ = 5; 5134346981Scy *pos++ = WLAN_TIMEOUT_KEY_LIFETIME; 5135346981Scy WPA_PUT_LE32(pos, conf->r0_key_lifetime); 5136346981Scy pos += 4; 5137346981Scy } 5138346981Scy#endif /* CONFIG_IEEE80211R_AP */ 5139346981Scy 5140346981Scy wpa_send_eapol(sm->wpa_auth, sm, 5141346981Scy (secure ? WPA_KEY_INFO_SECURE : 0) | 5142346981Scy (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ? 5143346981Scy WPA_KEY_INFO_MIC : 0) | 5144346981Scy WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL | 5145346981Scy WPA_KEY_INFO_KEY_TYPE, 5146346981Scy _rsc, sm->ANonce, kde, pos - kde, keyidx, encr); 5147346981Scy os_free(kde); 5148346981Scy return 0; 5149346981Scy} 5150346981Scy 5151346981Scy 5152346981Scyint wpa_auth_resend_group_m1(struct wpa_state_machine *sm, 5153346981Scy void (*cb)(void *ctx1, void *ctx2), 5154346981Scy void *ctx1, void *ctx2) 5155346981Scy{ 5156346981Scy u8 rsc[WPA_KEY_RSC_LEN]; 5157346981Scy struct wpa_group *gsm = sm->group; 5158346981Scy const u8 *kde; 5159346981Scy u8 *kde_buf = NULL, *pos, hdr[2]; 5160346981Scy#ifdef CONFIG_IEEE80211W 5161346981Scy u8 *opos; 5162346981Scy#endif /* CONFIG_IEEE80211W */ 5163346981Scy size_t kde_len; 5164346981Scy u8 *gtk; 5165346981Scy 5166346981Scy /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */ 5167346981Scy os_memset(rsc, 0, WPA_KEY_RSC_LEN); 5168346981Scy /* Use 0 RSC */ 5169346981Scy wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, 5170346981Scy "sending 1/2 msg of Group Key Handshake (TESTING)"); 5171346981Scy 5172346981Scy gtk = gsm->GTK[gsm->GN - 1]; 5173346981Scy if (sm->wpa == WPA_VERSION_WPA2) { 5174346981Scy kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len + 5175346981Scy ieee80211w_kde_len(sm) + ocv_oci_len(sm); 5176346981Scy kde_buf = os_malloc(kde_len); 5177346981Scy if (kde_buf == NULL) 5178346981Scy return -1; 5179346981Scy 5180346981Scy kde = pos = kde_buf; 5181346981Scy hdr[0] = gsm->GN & 0x03; 5182346981Scy hdr[1] = 0; 5183346981Scy pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, 5184346981Scy gtk, gsm->GTK_len); 5185346981Scy#ifdef CONFIG_IEEE80211W 5186346981Scy opos = pos; 5187346981Scy pos = ieee80211w_kde_add(sm, pos); 5188346981Scy if (pos - opos >= 5189346981Scy 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN) { 5190346981Scy /* skip KDE header and keyid */ 5191346981Scy opos += 2 + RSN_SELECTOR_LEN + 2; 5192346981Scy os_memset(opos, 0, 6); /* clear PN */ 5193346981Scy } 5194346981Scy#endif /* CONFIG_IEEE80211W */ 5195346981Scy if (ocv_oci_add(sm, &pos) < 0) { 5196346981Scy os_free(kde_buf); 5197346981Scy return -1; 5198346981Scy } 5199346981Scy kde_len = pos - kde; 5200346981Scy } else { 5201346981Scy kde = gtk; 5202346981Scy kde_len = gsm->GTK_len; 5203346981Scy } 5204346981Scy 5205346981Scy sm->eapol_status_cb = cb; 5206346981Scy sm->eapol_status_cb_ctx1 = ctx1; 5207346981Scy sm->eapol_status_cb_ctx2 = ctx2; 5208346981Scy 5209346981Scy wpa_send_eapol(sm->wpa_auth, sm, 5210346981Scy WPA_KEY_INFO_SECURE | 5211346981Scy (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ? 5212346981Scy WPA_KEY_INFO_MIC : 0) | 5213346981Scy WPA_KEY_INFO_ACK | 5214346981Scy (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0), 5215346981Scy rsc, NULL, kde, kde_len, gsm->GN, 1); 5216346981Scy 5217346981Scy os_free(kde_buf); 5218346981Scy return 0; 5219346981Scy} 5220346981Scy 5221346981Scy 5222346981Scyint wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth) 5223346981Scy{ 5224346981Scy if (!wpa_auth) 5225346981Scy return -1; 5226346981Scy eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL); 5227346981Scy return eloop_register_timeout(0, 0, wpa_rekey_gtk, wpa_auth, NULL); 5228346981Scy} 5229346981Scy 5230346981Scy#endif /* CONFIG_TESTING_OPTIONS */ 5231