/*
* WPA Supplicant - IEEE 802.11r - Fast BSS Transition
- * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "crypto/aes_wrap.h"
+#include "crypto/random.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "wpa.h"
#include "wpa_i.h"
-#include "wpa_ie.h"
#ifdef CONFIG_IEEE80211R
-struct wpa_ft_ies {
- const u8 *mdie;
- size_t mdie_len;
- const u8 *ftie;
- size_t ftie_len;
- const u8 *r1kh_id;
- const u8 *gtk;
- size_t gtk_len;
- const u8 *r0kh_id;
- size_t r0kh_id_len;
- const u8 *rsn;
- size_t rsn_len;
- const u8 *rsn_pmkid;
- const u8 *tie;
- size_t tie_len;
- const u8 *igtk;
- size_t igtk_len;
- const u8 *ric;
- size_t ric_len;
-};
-
-static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
- struct wpa_ft_ies *parse);
-
-
int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
- const struct wpa_eapol_key *key,
- struct wpa_ptk *ptk, size_t ptk_len)
+ const struct wpa_eapol_key *key, struct wpa_ptk *ptk)
{
u8 ptk_name[WPA_PMK_NAME_LEN];
const u8 *anonce = key->key_nonce;
wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, PMK_LEN);
wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name,
WPA_PMK_NAME_LEN);
- wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, anonce, sm->own_addr,
- sm->bssid, sm->pmk_r1_name,
- (u8 *) ptk, ptk_len, ptk_name);
- wpa_hexdump_key(MSG_DEBUG, "FT: PTK", (u8 *) ptk, ptk_len);
- wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);
-
- return 0;
+ return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, anonce, sm->own_addr,
+ sm->bssid, sm->pmk_r1_name, ptk, ptk_name,
+ sm->key_mgmt, sm->pairwise_cipher);
}
* @anonce: ANonce or %NULL if not yet available
* @pmk_name: PMKR0Name or PMKR1Name to be added into the RSN IE PMKID List
* @kck: 128-bit KCK for MIC or %NULL if no MIC is used
+ * @kck_len: KCK length in octets
* @target_ap: Target AP address
* @ric_ies: Optional IE(s), e.g., WMM TSPEC(s), for RIC-Request or %NULL
* @ric_ies_len: Length of ric_ies buffer in octets
*/
static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
const u8 *anonce, const u8 *pmk_name,
- const u8 *kck, const u8 *target_ap,
+ const u8 *kck, size_t kck_len,
+ const u8 *target_ap,
const u8 *ric_ies, size_t ric_ies_len,
const u8 *ap_mdie)
{
pos = (u8 *) (rsnie + 1);
/* Group Suite Selector */
- if (sm->group_cipher == WPA_CIPHER_CCMP)
- RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
- else if (sm->group_cipher == WPA_CIPHER_TKIP)
- RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
- else {
+ if (!wpa_cipher_valid_group(sm->group_cipher)) {
wpa_printf(MSG_WARNING, "FT: Invalid group cipher (%d)",
sm->group_cipher);
os_free(buf);
return NULL;
}
+ RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN,
+ sm->group_cipher));
pos += RSN_SELECTOR_LEN;
/* Pairwise Suite Count */
pos += 2;
/* Pairwise Suite List */
- if (sm->pairwise_cipher == WPA_CIPHER_CCMP)
- RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
- else if (sm->pairwise_cipher == WPA_CIPHER_TKIP)
- RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
- else {
+ if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) {
wpa_printf(MSG_WARNING, "FT: Invalid pairwise cipher (%d)",
sm->pairwise_cipher);
os_free(buf);
return NULL;
}
+ RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN,
+ sm->pairwise_cipher));
pos += RSN_SELECTOR_LEN;
/* Authenticated Key Management Suite Count */
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
else if (sm->key_mgmt == WPA_KEY_MGMT_FT_PSK)
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
+ else if (sm->key_mgmt == WPA_KEY_MGMT_FT_SAE)
+ RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE);
else {
wpa_printf(MSG_WARNING, "FT: Invalid key management type (%d)",
sm->key_mgmt);
/* Information element count */
ftie->mic_control[1] = 3 + ieee802_11_ie_count(ric_ies,
ric_ies_len);
- if (wpa_ft_mic(kck, sm->own_addr, target_ap, 5,
+ if (wpa_ft_mic(kck, kck_len, sm->own_addr, target_ap, 5,
((u8 *) mdie) - 2, 2 + sizeof(*mdie),
ftie_pos, 2 + *ftie_len,
(u8 *) rsnie, 2 + rsnie->len, ric_ies,
}
-static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
- struct wpa_ft_ies *parse)
-{
- const u8 *end, *pos;
-
- parse->ftie = ie;
- parse->ftie_len = ie_len;
-
- pos = ie + sizeof(struct rsn_ftie);
- end = ie + ie_len;
-
- while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
- switch (pos[0]) {
- case FTIE_SUBELEM_R1KH_ID:
- if (pos[1] != FT_R1KH_ID_LEN) {
- wpa_printf(MSG_DEBUG, "FT: Invalid R1KH-ID "
- "length in FTIE: %d", pos[1]);
- return -1;
- }
- parse->r1kh_id = pos + 2;
- break;
- case FTIE_SUBELEM_GTK:
- parse->gtk = pos + 2;
- parse->gtk_len = pos[1];
- break;
- case FTIE_SUBELEM_R0KH_ID:
- if (pos[1] < 1 || pos[1] > FT_R0KH_ID_MAX_LEN) {
- wpa_printf(MSG_DEBUG, "FT: Invalid R0KH-ID "
- "length in FTIE: %d", pos[1]);
- return -1;
- }
- parse->r0kh_id = pos + 2;
- parse->r0kh_id_len = pos[1];
- break;
-#ifdef CONFIG_IEEE80211W
- case FTIE_SUBELEM_IGTK:
- parse->igtk = pos + 2;
- parse->igtk_len = pos[1];
- break;
-#endif /* CONFIG_IEEE80211W */
- }
-
- pos += 2 + pos[1];
- }
-
- return 0;
-}
-
-
-static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
- struct wpa_ft_ies *parse)
-{
- const u8 *end, *pos;
- struct wpa_ie_data data;
- int ret;
- const struct rsn_ftie *ftie;
- int prot_ie_count = 0;
-
- os_memset(parse, 0, sizeof(*parse));
- if (ies == NULL)
- return 0;
-
- pos = ies;
- end = ies + ies_len;
- while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
- switch (pos[0]) {
- case WLAN_EID_RSN:
- parse->rsn = pos + 2;
- parse->rsn_len = pos[1];
- ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2,
- parse->rsn_len + 2,
- &data);
- if (ret < 0) {
- wpa_printf(MSG_DEBUG, "FT: Failed to parse "
- "RSN IE: %d", ret);
- return -1;
- }
- if (data.num_pmkid == 1 && data.pmkid)
- parse->rsn_pmkid = data.pmkid;
- break;
- case WLAN_EID_MOBILITY_DOMAIN:
- parse->mdie = pos + 2;
- parse->mdie_len = pos[1];
- break;
- case WLAN_EID_FAST_BSS_TRANSITION:
- if (pos[1] < sizeof(*ftie))
- return -1;
- ftie = (const struct rsn_ftie *) (pos + 2);
- prot_ie_count = ftie->mic_control[1];
- if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0)
- return -1;
- break;
- case WLAN_EID_TIMEOUT_INTERVAL:
- parse->tie = pos + 2;
- parse->tie_len = pos[1];
- break;
- case WLAN_EID_RIC_DATA:
- if (parse->ric == NULL)
- parse->ric = pos;
- }
-
- pos += 2 + pos[1];
- }
-
- if (prot_ie_count == 0)
- return 0; /* no MIC */
-
- /*
- * Check that the protected IE count matches with IEs included in the
- * frame.
- */
- if (parse->rsn)
- prot_ie_count--;
- if (parse->mdie)
- prot_ie_count--;
- if (parse->ftie)
- prot_ie_count--;
- if (parse->tie)
- prot_ie_count--;
- if (prot_ie_count < 0) {
- wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in "
- "the protected IE count");
- return -1;
- }
-
- if (prot_ie_count == 0 && parse->ric) {
- wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not "
- "included in protected IE count");
- return -1;
- }
-
- /* Determine the end of the RIC IE(s) */
- pos = parse->ric;
- while (pos && pos + 2 <= end && pos + 2 + pos[1] <= end &&
- prot_ie_count) {
- prot_ie_count--;
- pos += 2 + pos[1];
- }
- parse->ric_len = pos - parse->ric;
- if (prot_ie_count) {
- wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from "
- "frame", (int) prot_ie_count);
- return -1;
- }
-
- return 0;
-}
-
-
static int wpa_ft_install_ptk(struct wpa_sm *sm, const u8 *bssid)
{
int keylen;
wpa_printf(MSG_DEBUG, "FT: Installing PTK to the driver.");
- switch (sm->pairwise_cipher) {
- case WPA_CIPHER_CCMP:
- alg = WPA_ALG_CCMP;
- keylen = 16;
- break;
- case WPA_CIPHER_TKIP:
- alg = WPA_ALG_TKIP;
- keylen = 32;
- break;
- default:
+ if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) {
wpa_printf(MSG_WARNING, "FT: Unsupported pairwise cipher %d",
sm->pairwise_cipher);
return -1;
}
+ alg = wpa_cipher_to_alg(sm->pairwise_cipher);
+ keylen = wpa_cipher_key_len(sm->pairwise_cipher);
+
if (wpa_sm_set_key(sm, alg, bssid, 0, 1, null_rsc,
- sizeof(null_rsc), (u8 *) sm->ptk.tk1, keylen) < 0) {
+ sizeof(null_rsc), (u8 *) sm->ptk.tk, keylen) < 0) {
wpa_printf(MSG_WARNING, "FT: Failed to set PTK to the driver");
return -1;
}
size_t ft_ies_len;
/* Generate a new SNonce */
- if (os_get_random(sm->snonce, WPA_NONCE_LEN)) {
+ if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) {
wpa_printf(MSG_INFO, "FT: Failed to generate a new SNonce");
return -1;
}
ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name,
- NULL, sm->bssid, NULL, 0, mdie);
+ NULL, 0, sm->bssid, NULL, 0, mdie);
if (ft_ies) {
wpa_sm_update_ft_ies(sm, sm->mobility_domain,
ft_ies, ft_ies_len);
const u8 *ric_ies, size_t ric_ies_len)
{
u8 *ft_ies;
- size_t ft_ies_len, ptk_len;
+ size_t ft_ies_len;
struct wpa_ft_ies parse;
struct rsn_mdie *mdie;
struct rsn_ftie *ftie;
}
}
- if (sm->key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X &&
- sm->key_mgmt != WPA_KEY_MGMT_FT_PSK) {
+ if (!wpa_key_mgmt_ft(sm->key_mgmt)) {
wpa_printf(MSG_DEBUG, "FT: Reject FT IEs since FT is not "
"enabled for this connection");
return -1;
}
if (parse.r0kh_id_len != sm->r0kh_id_len ||
- os_memcmp(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0) {
+ os_memcmp_const(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0)
+ {
wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with "
"the current R0KH-ID");
wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE",
}
if (parse.rsn_pmkid == NULL ||
- os_memcmp(parse.rsn_pmkid, sm->pmk_r0_name, WPA_PMK_NAME_LEN)) {
+ os_memcmp_const(parse.rsn_pmkid, sm->pmk_r0_name, WPA_PMK_NAME_LEN))
+ {
wpa_printf(MSG_DEBUG, "FT: No matching PMKR0Name (PMKID) in "
"RSNIE");
return -1;
sm->pmk_r1_name, WPA_PMK_NAME_LEN);
bssid = target_ap;
- ptk_len = sm->pairwise_cipher == WPA_CIPHER_CCMP ? 48 : 64;
- wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, ftie->anonce, sm->own_addr,
- bssid, sm->pmk_r1_name,
- (u8 *) &sm->ptk, ptk_len, ptk_name);
- wpa_hexdump_key(MSG_DEBUG, "FT: PTK",
- (u8 *) &sm->ptk, ptk_len);
- wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);
+ if (wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, ftie->anonce,
+ sm->own_addr, bssid, sm->pmk_r1_name, &sm->ptk,
+ ptk_name, sm->key_mgmt, sm->pairwise_cipher) < 0)
+ return -1;
ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, ftie->anonce,
- sm->pmk_r1_name, sm->ptk.kck, bssid,
+ sm->pmk_r1_name,
+ sm->ptk.kck, sm->ptk.kck_len, bssid,
ric_ies, ric_ies_len,
parse.mdie ? parse.mdie - 2 : NULL);
if (ft_ies) {
if (sm == NULL)
return 0;
- if (sm->key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X &&
- sm->key_mgmt != WPA_KEY_MGMT_FT_PSK)
+ if (!wpa_key_mgmt_ft(sm->key_mgmt))
return 0;
return sm->ft_completed;
}
+void wpa_reset_ft_completed(struct wpa_sm *sm)
+{
+ if (sm != NULL)
+ sm->ft_completed = 0;
+}
+
+
static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
size_t gtk_elem_len)
{
return -1;
}
gtk_len = gtk_elem_len - 19;
- if (aes_unwrap(sm->ptk.kek, gtk_len / 8, gtk_elem + 11, gtk)) {
+ if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, gtk_len / 8, gtk_elem + 11,
+ gtk)) {
wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not "
"decrypt GTK");
return -1;
}
- switch (sm->group_cipher) {
- case WPA_CIPHER_CCMP:
- keylen = 16;
- rsc_len = 6;
- alg = WPA_ALG_CCMP;
- break;
- case WPA_CIPHER_TKIP:
- keylen = 32;
- rsc_len = 6;
- alg = WPA_ALG_TKIP;
- break;
- case WPA_CIPHER_WEP104:
- keylen = 13;
- rsc_len = 0;
- alg = WPA_ALG_WEP;
- break;
- case WPA_CIPHER_WEP40:
- keylen = 5;
- rsc_len = 0;
- alg = WPA_ALG_WEP;
- break;
- default:
+ keylen = wpa_cipher_key_len(sm->group_cipher);
+ rsc_len = wpa_cipher_rsc_len(sm->group_cipher);
+ alg = wpa_cipher_to_alg(sm->group_cipher);
+ if (alg == WPA_ALG_NONE) {
wpa_printf(MSG_WARNING, "WPA: Unsupported Group Cipher %d",
sm->group_cipher);
return -1;
}
wpa_hexdump_key(MSG_DEBUG, "FT: GTK from Reassoc Resp", gtk, keylen);
- if (wpa_sm_set_key(sm, alg, (u8 *) "\xff\xff\xff\xff\xff\xff",
- keyidx, 0, gtk_elem + 3, rsc_len, gtk, keylen) <
- 0) {
+ if (sm->group_cipher == WPA_CIPHER_TKIP) {
+ /* Swap Tx/Rx keys for Michael MIC */
+ u8 tmp[8];
+ os_memcpy(tmp, gtk + 16, 8);
+ os_memcpy(gtk + 16, gtk + 24, 8);
+ os_memcpy(gtk + 24, tmp, 8);
+ }
+ if (wpa_sm_set_key(sm, alg, broadcast_ether_addr, keyidx, 0,
+ gtk_elem + 3, rsc_len, gtk, keylen) < 0) {
wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to the "
"driver.");
return -1;
return -1;
}
- if (aes_unwrap(sm->ptk.kek, WPA_IGTK_LEN / 8, igtk_elem + 9, igtk)) {
+ if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, WPA_IGTK_LEN / 8,
+ igtk_elem + 9, igtk)) {
wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not "
"decrypt IGTK");
return -1;
wpa_hexdump_key(MSG_DEBUG, "FT: IGTK from Reassoc Resp", igtk,
WPA_IGTK_LEN);
- if (wpa_sm_set_key(sm, WPA_ALG_IGTK, (u8 *) "\xff\xff\xff\xff\xff\xff",
- keyidx, 0, igtk_elem + 2, 6, igtk, WPA_IGTK_LEN) <
- 0) {
+ if (wpa_sm_set_key(sm, WPA_ALG_IGTK, broadcast_ether_addr, keyidx, 0,
+ igtk_elem + 2, 6, igtk, WPA_IGTK_LEN) < 0) {
wpa_printf(MSG_WARNING, "WPA: Failed to set IGTK to the "
"driver.");
return -1;
struct rsn_mdie *mdie;
struct rsn_ftie *ftie;
unsigned int count;
- u8 mic[16];
+ u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len);
- if (sm->key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X &&
- sm->key_mgmt != WPA_KEY_MGMT_FT_PSK) {
+ if (!wpa_key_mgmt_ft(sm->key_mgmt)) {
wpa_printf(MSG_DEBUG, "FT: Reject FT IEs since FT is not "
"enabled for this connection");
return -1;
}
if (parse.r0kh_id_len != sm->r0kh_id_len ||
- os_memcmp(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0) {
+ os_memcmp_const(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0)
+ {
wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with "
"the current R0KH-ID");
wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE",
return -1;
}
- if (os_memcmp(parse.r1kh_id, sm->r1kh_id, FT_R1KH_ID_LEN) != 0) {
+ if (os_memcmp_const(parse.r1kh_id, sm->r1kh_id, FT_R1KH_ID_LEN) != 0) {
wpa_printf(MSG_DEBUG, "FT: Unknown R1KH-ID used in "
"ReassocResp");
return -1;
}
if (parse.rsn_pmkid == NULL ||
- os_memcmp(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN)) {
+ os_memcmp_const(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN))
+ {
wpa_printf(MSG_DEBUG, "FT: No matching PMKR1Name (PMKID) in "
"RSNIE (pmkid=%d)", !!parse.rsn_pmkid);
return -1;
}
count = 3;
- if (parse.tie)
- count++;
+ if (parse.ric)
+ count += ieee802_11_ie_count(parse.ric, parse.ric_len);
if (ftie->mic_control[1] != count) {
wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC "
"Control: received %u expected %u",
return -1;
}
- if (wpa_ft_mic(sm->ptk.kck, sm->own_addr, src_addr, 6,
+ if (wpa_ft_mic(sm->ptk.kck, sm->ptk.kck_len, sm->own_addr, src_addr, 6,
parse.mdie - 2, parse.mdie_len + 2,
parse.ftie - 2, parse.ftie_len + 2,
parse.rsn - 2, parse.rsn_len + 2,
return -1;
}
- if (os_memcmp(mic, ftie->mic, 16) != 0) {
+ if (os_memcmp_const(mic, ftie->mic, 16) != 0) {
wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE");
wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", ftie->mic, 16);
wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, 16);
if (parse.ric) {
wpa_hexdump(MSG_MSGDUMP, "FT: RIC Response",
parse.ric, parse.ric_len);
- /* TODO: parse response and inform driver about results */
+ /* TODO: parse response and inform driver about results when
+ * using wpa_supplicant SME */
}
+ wpa_printf(MSG_DEBUG, "FT: Completed successfully");
+
return 0;
}
MAC2STR(target_ap));
/* Generate a new SNonce */
- if (os_get_random(sm->snonce, WPA_NONCE_LEN)) {
+ if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) {
wpa_printf(MSG_INFO, "FT: Failed to generate a new SNonce");
return -1;
}
ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name,
- NULL, target_ap, NULL, 0, mdie);
+ NULL, 0, target_ap, NULL, 0, mdie);
if (ft_ies) {
sm->over_the_ds_in_progress = 1;
os_memcpy(sm->target_ap, target_ap, ETH_ALEN);