diff --git a/tests/hwsim/test_fils.py b/tests/hwsim/test_fils.py index 39b48e980..9998299d8 100644 --- a/tests/hwsim/test_fils.py +++ b/tests/hwsim/test_fils.py @@ -2358,3 +2358,54 @@ def test_fils_discovery_frame(dev, apdev, params): eap="PSK", identity="psk.user@example.com", password_hex="0123456789abcdef0123456789abcdef", erp="1", scan_freq="2412") + +def test_fils_offload_to_driver(dev, apdev, params): + """FILS offload to driver""" + check_fils_capa(dev[0]) + check_erp_capa(dev[0]) + run_fils_offload_to_driver(dev[0], apdev, params) + +def test_fils_offload_to_driver2(dev, apdev, params): + """FILS offload to driver""" + wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') + wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") + run_fils_offload_to_driver(wpas, apdev, params) + +def run_fils_offload_to_driver(dev, apdev, params): + start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst")) + + bssid = apdev[0]['bssid'] + params = hostapd.wpa2_eap_params(ssid="fils") + params['wpa_key_mgmt'] = "FILS-SHA256" + params['auth_server_port'] = "18128" + params['erp_send_reauth_start'] = '1' + params['erp_domain'] = 'example.com' + params['fils_realm'] = 'example.com' + params['disable_pmksa_caching'] = '1' + hapd = hostapd.add_ap(apdev[0]['ifname'], params) + + dev.request("ERP_FLUSH") + id = dev.connect("fils", key_mgmt="FILS-SHA256", + eap="PSK", identity="psk.user@example.com", + password_hex="0123456789abcdef0123456789abcdef", + erp="1", scan_freq="2412") + + p = "freq=2412 authorized=1 fils_erp_next_seq_num=4" + if "OK" not in dev.request("DRIVER_EVENT ASSOC " + p): + raise Exception("DRIVER_EVENT ASSOC did not succeed") + dev.wait_connected() + + dev.request("DISCONNECT") + dev.wait_disconnected() + dev.dump_monitor() + + dev.select_network(id, freq=2412) + dev.wait_connected() + dev.dump_monitor() + + # This does not really work properly with SME-in-wpa_supplicant case + p = "freq=2412 authorized=1 fils_erp_next_seq_num=4" + if "OK" not in dev.request("DRIVER_EVENT ASSOC " + p): + raise Exception("DRIVER_EVENT ASSOC did not succeed") + + dev.wait_connected() diff --git a/tests/hwsim/test_wpas_ctrl.py b/tests/hwsim/test_wpas_ctrl.py index 1e4879874..210c11907 100644 --- a/tests/hwsim/test_wpas_ctrl.py +++ b/tests/hwsim/test_wpas_ctrl.py @@ -1402,6 +1402,8 @@ def test_wpas_ctrl_driver_event(dev, apdev): """wpa_supplicant ctrl_iface DRIVER_EVENT""" if "FAIL" not in dev[0].request("DRIVER_EVENT foo"): raise Exception("Invalid DRIVER_EVENT accepted") + if "OK" not in dev[0].request("DRIVER_EVENT ASSOC reassoc=1 req_ies=0000 resp_ies=0000 resp_frame=0000 beacon_ies=0000 freq=2412 wmm::info_bitmap=0 wmm::uapsd_queues=0 addr=02:02:02:02:02:02 authorized=0 key_replay_ctr=00 ptk_kck=00 ptk_kek=00 subnet_status=0 fils_erp_next_seq_num=0 fils_pmk=00 fils_pmkid=" + 16*"00"): + raise Exception("DRIVER_EVENT ASSOC did not succeed") @remote_compatible def test_wpas_ctrl_eapol_rx(dev, apdev): diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 0cf2a44ff..062c64ee4 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -9313,6 +9313,132 @@ fail: } +static int wpas_ctrl_iface_driver_event_assoc(struct wpa_supplicant *wpa_s, + char *param) +{ + union wpa_event_data event; + struct assoc_info *ai; + char *ctx = NULL; + int ret = -1; + struct wpabuf *req_ies = NULL; + struct wpabuf *resp_ies = NULL; + struct wpabuf *resp_frame = NULL; + struct wpabuf *beacon_ies = NULL; + struct wpabuf *key_replay_ctr = NULL; + struct wpabuf *ptk_kck = NULL; + struct wpabuf *ptk_kek = NULL; + struct wpabuf *fils_pmk = NULL; + char *str, *pos; + u8 addr[ETH_ALEN]; + u8 fils_pmkid[PMKID_LEN]; + + os_memset(&event, 0, sizeof(event)); + ai = &event.assoc_info; + + while ((str = str_token(param, " ", &ctx))) { + pos = os_strchr(str, '='); + if (!pos) + goto fail; + *pos++ = '\0'; + + if (os_strcmp(str, "reassoc") == 0) { + ai->reassoc = atoi(pos); + } else if (os_strcmp(str, "req_ies") == 0) { + wpabuf_free(req_ies); + req_ies = wpabuf_parse_bin(pos); + if (!req_ies) + goto fail; + ai->req_ies = wpabuf_head(req_ies); + ai->req_ies_len = wpabuf_len(req_ies); + } else if (os_strcmp(str, "resp_ies") == 0) { + wpabuf_free(resp_ies); + resp_ies = wpabuf_parse_bin(pos); + if (!resp_ies) + goto fail; + ai->resp_ies = wpabuf_head(resp_ies); + ai->resp_ies_len = wpabuf_len(resp_ies); + } else if (os_strcmp(str, "resp_frame") == 0) { + wpabuf_free(resp_frame); + resp_frame = wpabuf_parse_bin(pos); + if (!resp_frame) + goto fail; + ai->resp_frame = wpabuf_head(resp_frame); + ai->resp_frame_len = wpabuf_len(resp_frame); + } else if (os_strcmp(str, "beacon_ies") == 0) { + wpabuf_free(beacon_ies); + beacon_ies = wpabuf_parse_bin(pos); + if (!beacon_ies) + goto fail; + ai->beacon_ies = wpabuf_head(beacon_ies); + ai->beacon_ies_len = wpabuf_len(beacon_ies); + } else if (os_strcmp(str, "freq") == 0) { + ai->freq = atoi(pos); + } else if (os_strcmp(str, "wmm::info_bitmap") == 0) { + ai->wmm_params.info_bitmap = atoi(pos); + } else if (os_strcmp(str, "wmm::uapsd_queues") == 0) { + ai->wmm_params.uapsd_queues = atoi(pos); + } else if (os_strcmp(str, "addr") == 0) { + if (hwaddr_aton(pos, addr)) + goto fail; + ai->addr = addr; + } else if (os_strcmp(str, "authorized") == 0) { + ai->authorized = atoi(pos); + } else if (os_strcmp(str, "key_replay_ctr") == 0) { + wpabuf_free(key_replay_ctr); + key_replay_ctr = wpabuf_parse_bin(pos); + if (!key_replay_ctr) + goto fail; + ai->key_replay_ctr = wpabuf_head(key_replay_ctr); + ai->key_replay_ctr_len = wpabuf_len(key_replay_ctr); + } else if (os_strcmp(str, "ptk_kck") == 0) { + wpabuf_free(ptk_kck); + ptk_kck = wpabuf_parse_bin(pos); + if (!ptk_kck) + goto fail; + ai->ptk_kck = wpabuf_head(ptk_kck); + ai->ptk_kck_len = wpabuf_len(ptk_kck); + } else if (os_strcmp(str, "ptk_kek") == 0) { + wpabuf_free(ptk_kek); + ptk_kek = wpabuf_parse_bin(pos); + if (!ptk_kek) + goto fail; + ai->ptk_kek = wpabuf_head(ptk_kek); + ai->ptk_kek_len = wpabuf_len(ptk_kek); + } else if (os_strcmp(str, "subnet_status") == 0) { + ai->subnet_status = atoi(pos); + } else if (os_strcmp(str, "fils_erp_next_seq_num") == 0) { + ai->fils_erp_next_seq_num = atoi(pos); + } else if (os_strcmp(str, "fils_pmk") == 0) { + wpabuf_free(fils_pmk); + fils_pmk = wpabuf_parse_bin(pos); + if (!fils_pmk) + goto fail; + ai->fils_pmk = wpabuf_head(fils_pmk); + ai->fils_pmk_len = wpabuf_len(fils_pmk); + } else if (os_strcmp(str, "fils_pmkid") == 0) { + if (hexstr2bin(pos, fils_pmkid, PMKID_LEN) < 0) + goto fail; + ai->fils_pmkid = fils_pmkid; + } else { + goto fail; + } + } + + wpa_supplicant_event(wpa_s, EVENT_ASSOC, &event); + ret = 0; +fail: + wpabuf_free(req_ies); + wpabuf_free(resp_ies); + wpabuf_free(resp_frame); + wpabuf_free(beacon_ies); + wpabuf_free(key_replay_ctr); + wpabuf_free(ptk_kck); + wpabuf_free(ptk_kek); + wpabuf_free(fils_pmk); + return ret; +} + + static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd) { char *pos, *param; @@ -9345,6 +9471,8 @@ static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd) return 0; } else if (os_strcmp(cmd, "SCAN_RES") == 0) { return wpas_ctrl_iface_driver_scan_res(wpa_s, param); + } else if (os_strcmp(cmd, "ASSOC") == 0) { + return wpas_ctrl_iface_driver_event_assoc(wpa_s, param); } else { wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s", cmd);