]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
PASN: Set secure ranging context to driver after association
authorVinay Gannevaram <quic_vganneva@quicinc.com>
Thu, 7 Jul 2022 21:17:08 +0000 (02:47 +0530)
committerJouni Malinen <j@w1.fi>
Fri, 2 Sep 2022 14:07:56 +0000 (17:07 +0300)
After the secure association and PTK derivation are completed, if the
device supports LTF keyseed, generate the LTF keyseed using KDK and set
the ranging context to the driver by using the command
QCA_NL80211_VENDOR_SUBCMD_SECURE_RANGING_CONTEXT.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
src/ap/wpa_auth.c
src/ap/wpa_auth.h
src/ap/wpa_auth_ft.c
src/ap/wpa_auth_glue.c
src/rsn_supp/wpa.c
src/rsn_supp/wpa.h
src/rsn_supp/wpa_ft.c
src/rsn_supp/wpa_i.h
wpa_supplicant/wpas_glue.c

index 53211f6258ca5908fb72d841b731b8188944d9f5..73feac4291b1c511d051967bdaed10efa45bf86a 100644 (file)
@@ -149,6 +149,20 @@ static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
 }
 
 
+#ifdef CONFIG_PASN
+static inline int wpa_auth_set_ltf_keyseed(struct wpa_authenticator *wpa_auth,
+                                          const u8 *peer_addr,
+                                          const u8 *ltf_keyseed,
+                                          size_t ltf_keyseed_len)
+{
+       if (!wpa_auth->cb->set_ltf_keyseed)
+               return -1;
+       return wpa_auth->cb->set_ltf_keyseed(wpa_auth->cb_ctx, peer_addr,
+                                            ltf_keyseed, ltf_keyseed_len);
+}
+#endif /* CONFIG_PASN */
+
+
 static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth,
                                      const u8 *addr, int idx, u8 *seq)
 {
@@ -2311,6 +2325,7 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
        const u8 *z = NULL;
        size_t z_len = 0, kdk_len;
        int akmp;
+       int ret;
 
        if (sm->wpa_auth->conf.force_kdk_derivation ||
            (sm->wpa_auth->conf.secure_ltf &&
@@ -2324,16 +2339,33 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
                if (sm->ft_completed) {
                        u8 ptk_name[WPA_PMK_NAME_LEN];
 
-                       return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len,
-                                                sm->SNonce, sm->ANonce,
-                                                sm->addr, sm->wpa_auth->addr,
-                                                sm->pmk_r1_name,
-                                                ptk, ptk_name,
-                                                sm->wpa_key_mgmt,
-                                                sm->pairwise,
-                                                kdk_len);
+                       ret = wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len,
+                                               sm->SNonce, sm->ANonce,
+                                               sm->addr, sm->wpa_auth->addr,
+                                               sm->pmk_r1_name, ptk,
+                                               ptk_name, sm->wpa_key_mgmt,
+                                               sm->pairwise, kdk_len);
+               } else {
+                       ret = wpa_auth_derive_ptk_ft(sm, ptk);
+               }
+               if (ret) {
+                       wpa_printf(MSG_ERROR, "FT: PTK derivation failed");
+                       return ret;
+               }
+
+#ifdef CONFIG_PASN
+               if (sm->wpa_auth->conf.secure_ltf &&
+                   ieee802_11_rsnx_capab(sm->rsnxe,
+                                         WLAN_RSNX_CAPAB_SECURE_LTF)) {
+                       ret = wpa_ltf_keyseed(ptk, sm->wpa_key_mgmt,
+                                             sm->pairwise);
+                       if (ret) {
+                               wpa_printf(MSG_ERROR,
+                                          "FT: LTF keyseed derivation failed");
+                       }
                }
-               return wpa_auth_derive_ptk_ft(sm, ptk);
+#endif /* CONFIG_PASN */
+               return ret;
        }
 #endif /* CONFIG_IEEE80211R_AP */
 
@@ -2347,9 +2379,27 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
        akmp = sm->wpa_key_mgmt;
        if (force_sha256)
                akmp |= WPA_KEY_MGMT_PSK_SHA256;
-       return wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion",
-                             sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce,
-                             ptk, akmp, sm->pairwise, z, z_len, kdk_len);
+       ret = wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion",
+                            sm->wpa_auth->addr, sm->addr, sm->ANonce,
+                            snonce, ptk, akmp, sm->pairwise, z, z_len,
+                            kdk_len);
+       if (ret) {
+               wpa_printf(MSG_DEBUG,
+                          "WPA: PTK derivation failed");
+               return ret;
+       }
+
+#ifdef CONFIG_PASN
+       if (sm->wpa_auth->conf.secure_ltf &&
+           ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)) {
+               ret = wpa_ltf_keyseed(ptk, sm->wpa_key_mgmt, sm->pairwise);
+               if (ret) {
+                       wpa_printf(MSG_DEBUG,
+                                  "WPA: LTF keyseed derivation failed");
+               }
+       }
+#endif /* CONFIG_PASN */
+       return ret;
 }
 
 
@@ -2380,6 +2430,19 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
                              fils_ft, &fils_ft_len, kdk_len);
        if (res < 0)
                return res;
+
+#ifdef CONFIG_PASN
+       if (sm->wpa_auth->conf.secure_ltf &&
+           ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)) {
+               res = wpa_ltf_keyseed(&sm->PTK, sm->wpa_key_mgmt, sm->pairwise);
+               if (res) {
+                       wpa_printf(MSG_ERROR,
+                                  "FILS: LTF keyseed derivation failed");
+                       return res;
+               }
+       }
+#endif /* CONFIG_PASN */
+
        sm->PTK_valid = true;
        sm->tk_already_set = false;
 
@@ -2883,6 +2946,19 @@ int fils_set_tk(struct wpa_state_machine *sm)
                wpa_printf(MSG_DEBUG, "FILS: Failed to set TK to the driver");
                return -1;
        }
+
+#ifdef CONFIG_PASN
+       if (sm->wpa_auth->conf.secure_ltf &&
+           ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF) &&
+           wpa_auth_set_ltf_keyseed(sm->wpa_auth, sm->addr,
+                                    sm->PTK.ltf_keyseed,
+                                    sm->PTK.ltf_keyseed_len)) {
+               wpa_printf(MSG_ERROR,
+                          "FILS: Failed to set LTF keyseed to driver");
+               return -1;
+       }
+#endif /* CONFIG_PASN */
+
        sm->pairwise_set = true;
        sm->tk_already_set = true;
 
@@ -3481,6 +3557,21 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
                        return;
                }
 
+#ifdef CONFIG_PASN
+               if (sm->wpa_auth->conf.secure_ltf &&
+                   ieee802_11_rsnx_capab(sm->rsnxe,
+                                         WLAN_RSNX_CAPAB_SECURE_LTF) &&
+                   wpa_auth_set_ltf_keyseed(sm->wpa_auth, sm->addr,
+                                            sm->PTK.ltf_keyseed,
+                                            sm->PTK.ltf_keyseed_len)) {
+                       wpa_printf(MSG_ERROR,
+                                  "WPA: Failed to set LTF keyseed to driver");
+                       wpa_sta_disconnect(sm->wpa_auth, sm->addr,
+                                          WLAN_REASON_PREV_AUTH_NOT_VALID);
+                       return;
+               }
+#endif /* CONFIG_PASN */
+
                /* WPA2 send GTK in the 4-way handshake */
                secure = 1;
                gtk = gsm->GTK[gsm->GN - 1];
@@ -3692,6 +3783,22 @@ SM_STATE(WPA_PTK, PTKINITDONE)
                                           WLAN_REASON_PREV_AUTH_NOT_VALID);
                        return;
                }
+
+#ifdef CONFIG_PASN
+               if (sm->wpa_auth->conf.secure_ltf &&
+                   ieee802_11_rsnx_capab(sm->rsnxe,
+                                         WLAN_RSNX_CAPAB_SECURE_LTF) &&
+                   wpa_auth_set_ltf_keyseed(sm->wpa_auth, sm->addr,
+                                            sm->PTK.ltf_keyseed,
+                                            sm->PTK.ltf_keyseed_len)) {
+                       wpa_printf(MSG_ERROR,
+                                  "WPA: Failed to set LTF keyseed to driver");
+                       wpa_sta_disconnect(sm->wpa_auth, sm->addr,
+                                          WLAN_REASON_PREV_AUTH_NOT_VALID);
+                       return;
+               }
+#endif /* CONFIG_PASN */
+
                /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
                sm->pairwise_set = true;
 
index c6ba422f7db723f00ae931e7744b23e0acff3d02..e8e6a8a6b77c54ce08d9c10d9fe09a6ad211e7ae 100644 (file)
@@ -350,6 +350,10 @@ struct wpa_auth_callbacks {
 #ifdef CONFIG_MESH
        int (*start_ampe)(void *ctx, const u8 *sta_addr);
 #endif /* CONFIG_MESH */
+#ifdef CONFIG_PASN
+       int (*set_ltf_keyseed)(void *ctx, const u8 *addr, const u8 *ltf_keyseed,
+                              size_t ltf_keyseed_len);
+#endif /* CONFIG_PASN */
 };
 
 struct wpa_authenticator * wpa_init(const u8 *addr,
index 7a97613598cd42d3025def815556edb34030545c..1b1324b8d1ba878766359ac74050e9f1da5b72a8 100644 (file)
@@ -2805,6 +2805,20 @@ static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
 }
 
 
+#ifdef CONFIG_PASN
+static inline int wpa_auth_set_ltf_keyseed(struct wpa_authenticator *wpa_auth,
+                                          const u8 *peer_addr,
+                                          const u8 *ltf_keyseed,
+                                          size_t ltf_keyseed_len)
+{
+       if (!wpa_auth->cb->set_ltf_keyseed)
+               return -1;
+       return wpa_auth->cb->set_ltf_keyseed(wpa_auth->cb_ctx, peer_addr,
+                                            ltf_keyseed, ltf_keyseed_len);
+}
+#endif /* CONFIG_PASN */
+
+
 static inline int wpa_auth_add_sta_ft(struct wpa_authenticator *wpa_auth,
                                      const u8 *addr)
 {
@@ -2849,6 +2863,18 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm, int retry)
                             sm->PTK.tk, klen, KEY_FLAG_PAIRWISE_RX_TX))
                return;
 
+#ifdef CONFIG_PASN
+       if (sm->wpa_auth->conf.secure_ltf &&
+           ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF) &&
+           wpa_auth_set_ltf_keyseed(sm->wpa_auth, sm->addr,
+                                    sm->PTK.ltf_keyseed,
+                                    sm->PTK.ltf_keyseed_len)) {
+               wpa_printf(MSG_ERROR,
+                          "FT: Failed to set LTF keyseed to driver");
+               return;
+       }
+#endif /* CONFIG_PASN */
+
        /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
        sm->pairwise_set = true;
        sm->tk_already_set = true;
@@ -3210,6 +3236,15 @@ pmk_r1_derived:
                              pairwise, kdk_len) < 0)
                return WLAN_STATUS_UNSPECIFIED_FAILURE;
 
+#ifdef CONFIG_PASN
+       if (sm->wpa_auth->conf.secure_ltf &&
+           ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF) &&
+           wpa_ltf_keyseed(&sm->PTK, sm->wpa_key_mgmt, pairwise)) {
+               wpa_printf(MSG_DEBUG, "FT: Failed to derive LTF keyseed");
+               return WLAN_STATUS_UNSPECIFIED_FAILURE;
+       }
+#endif /* CONFIG_PASN */
+
        sm->pairwise = pairwise;
        sm->PTK_valid = true;
        sm->tk_already_set = false;
index 1b4852cea542fc8ba2010ec51785f9c1c79d60f8..f388ffe9ffa62f88bd32379b5f4d5c0be49b956d 100644 (file)
@@ -1470,6 +1470,21 @@ static void hostapd_request_radius_psk(void *ctx, const u8 *addr, int key_mgmt,
 #endif /* CONFIG_NO_RADIUS */
 
 
+#ifdef CONFIG_PASN
+static int hostapd_set_ltf_keyseed(void *ctx, const u8 *peer_addr,
+                                  const u8 *ltf_keyseed,
+                                  size_t ltf_keyseed_len)
+{
+       struct hostapd_data *hapd = ctx;
+
+       return hostapd_drv_set_secure_ranging_ctx(hapd, hapd->own_addr,
+                                                 peer_addr, 0, 0, NULL,
+                                                 ltf_keyseed_len,
+                                                 ltf_keyseed, 0);
+}
+#endif /* CONFIG_PASN */
+
+
 int hostapd_setup_wpa(struct hostapd_data *hapd)
 {
        struct wpa_auth_config _conf;
@@ -1516,6 +1531,9 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
 #ifndef CONFIG_NO_RADIUS
                .request_radius_psk = hostapd_request_radius_psk,
 #endif /* CONFIG_NO_RADIUS */
+#ifdef CONFIG_PASN
+               .set_ltf_keyseed = hostapd_set_ltf_keyseed,
+#endif /* CONFIG_PASN */
        };
        const u8 *wpa_ie;
        size_t wpa_ie_len;
index 3e39947a50c6a83688fee21afc4dd65d05f7a680..af79551407a176c1d0ce34ced99117455194c15d 100644 (file)
@@ -585,6 +585,7 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
 static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr,
                          const struct wpa_eapol_key *key, struct wpa_ptk *ptk)
 {
+       int ret;
        const u8 *z = NULL;
        size_t z_len = 0, kdk_len;
        int akmp;
@@ -618,11 +619,23 @@ static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr,
        else
                kdk_len = 0;
 
-       return wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion",
-                             sm->own_addr, sm->bssid, sm->snonce,
-                             key->key_nonce, ptk, akmp,
-                             sm->pairwise_cipher, z, z_len,
-                             kdk_len);
+       ret = wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion",
+                            sm->own_addr, sm->bssid, sm->snonce,
+                            key->key_nonce, ptk, akmp,
+                            sm->pairwise_cipher, z, z_len,
+                            kdk_len);
+       if (ret) {
+               wpa_printf(MSG_ERROR, "WPA: PTK derivation failed");
+               return ret;
+       }
+
+#ifdef CONFIG_PASN
+       if (sm->secure_ltf &&
+           ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF))
+               ret = wpa_ltf_keyseed(ptk, akmp, sm->pairwise_cipher);
+#endif /* CONFIG_PASN */
+
+       return ret;
 }
 
 
@@ -976,6 +989,20 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm,
                return -1;
        }
 
+#ifdef CONFIG_PASN
+       if (sm->secure_ltf &&
+           ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF) &&
+           wpa_sm_set_ltf_keyseed(sm, sm->own_addr, sm->bssid,
+                                  sm->ptk.ltf_keyseed_len,
+                                  sm->ptk.ltf_keyseed) < 0) {
+               wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+                       "WPA: Failed to set LTF keyseed to the driver (keylen=%zu bssid="
+                       MACSTR ")", sm->ptk.ltf_keyseed_len,
+                       MAC2STR(sm->bssid));
+               return -1;
+       }
+#endif /* CONFIG_PASN */
+
        wpa_sm_store_ptk(sm, sm->bssid, sm->pairwise_cipher,
                         sm->dot11RSNAConfigPMKLifetime, &sm->ptk);
 
@@ -4452,6 +4479,15 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
                goto fail;
        }
 
+#ifdef CONFIG_PASN
+       if (sm->secure_ltf &&
+           ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF) &&
+           wpa_ltf_keyseed(&sm->ptk, sm->key_mgmt, sm->pairwise_cipher)) {
+               wpa_printf(MSG_DEBUG, "FILS: Failed to derive LTF keyseed");
+               goto fail;
+       }
+#endif /* CONFIG_PASN */
+
        wpabuf_clear_free(dh_ss);
        dh_ss = NULL;
 
index df32240c666f88aed6334db6729a7c602e915558..80262a23cd767dbd3bc923e401471ac88014bc8c 100644 (file)
@@ -93,6 +93,11 @@ struct wpa_sm_ctx {
        void (*transition_disable)(void *ctx, u8 bitmap);
        void (*store_ptk)(void *ctx, u8 *addr, int cipher,
                          u32 life_time, const struct wpa_ptk *ptk);
+#ifdef CONFIG_PASN
+       int (*set_ltf_keyseed)(void *ctx, const u8 *own_addr,
+                              const u8 *peer_addr, size_t ltf_keyseed_len,
+                              const u8 *ltf_keyseed);
+#endif /* CONFIG_PASN */
 };
 
 
index 9d4044c14cc7c49d6df7bdedf84bba5a04f21862..c681a99df4a0fa7340b74fe6aede448e2ff622f5 100644 (file)
@@ -41,6 +41,7 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
        int use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt);
        const u8 *mpmk;
        size_t mpmk_len, kdk_len;
+       int ret = 0;
 
        if (sm->xxkey_len > 0) {
                mpmk = sm->xxkey;
@@ -75,10 +76,22 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
        else
                kdk_len = 0;
 
-       return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len, sm->snonce, anonce,
-                                sm->own_addr, sm->bssid, sm->pmk_r1_name, ptk,
-                                ptk_name, sm->key_mgmt, sm->pairwise_cipher,
-                                kdk_len);
+       ret = wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len, sm->snonce,
+                               anonce, sm->own_addr, sm->bssid,
+                               sm->pmk_r1_name, ptk, ptk_name, sm->key_mgmt,
+                               sm->pairwise_cipher, kdk_len);
+       if (ret) {
+               wpa_printf(MSG_ERROR, "FT: PTK derivation failed");
+               return ret;
+       }
+
+#ifdef CONFIG_PASN
+       if (sm->secure_ltf &&
+           ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF))
+               ret = wpa_ltf_keyseed(ptk, sm->key_mgmt, sm->pairwise_cipher);
+#endif /* CONFIG_PASN */
+
+       return ret;
 }
 
 
@@ -688,6 +701,15 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
                              kdk_len) < 0)
                return -1;
 
+#ifdef CONFIG_PASN
+       if (sm->secure_ltf &&
+           ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF) &&
+           wpa_ltf_keyseed(&sm->ptk, sm->key_mgmt, sm->pairwise_cipher)) {
+               wpa_printf(MSG_DEBUG, "FT: Failed to derive LTF keyseed");
+               return -1;
+       }
+#endif /* CONFIG_PASN */
+
        if (wpa_key_mgmt_fils(sm->key_mgmt)) {
                kck = sm->ptk.kck2;
                kck_len = sm->ptk.kck2_len;
index fabd6cb26bea1d3dcd59c7ff61d9663a76d800ff..3811c3bc4681d4333dd17b859c8188bcdd44fbbc 100644 (file)
@@ -483,6 +483,18 @@ static inline void wpa_sm_store_ptk(struct wpa_sm *sm,
                                   ptk);
 }
 
+#ifdef CONFIG_PASN
+static inline int wpa_sm_set_ltf_keyseed(struct wpa_sm *sm, const u8 *own_addr,
+                                        const u8 *peer_addr,
+                                        size_t ltf_keyseed_len,
+                                        const u8 *ltf_keyseed)
+{
+       WPA_ASSERT(sm->ctx->set_ltf_keyseed);
+       return sm->ctx->set_ltf_keyseed(sm->ctx->ctx, own_addr, peer_addr,
+                                       ltf_keyseed_len, ltf_keyseed);
+}
+#endif /* CONFIG_PASN */
+
 int wpa_eapol_key_send(struct wpa_sm *sm, struct wpa_ptk *ptk,
                       int ver, const u8 *dest, u16 proto,
                       u8 *msg, size_t msg_len, u8 *key_mic);
index 35ca12308ac980d505d70e2bc29cced631462663..c5cfa92e57203ed95f3bd8b900bda1869e57192c 100644 (file)
@@ -1385,6 +1385,21 @@ static void wpa_supplicant_store_ptk(void *ctx, u8 *addr, int cipher,
 #endif /* CONFIG_NO_WPA */
 
 
+#ifdef CONFIG_PASN
+static int wpa_supplicant_set_ltf_keyseed(void *_wpa_s, const u8 *own_addr,
+                                         const u8 *peer_addr,
+                                         size_t ltf_keyseed_len,
+                                         const u8 *ltf_keyseed)
+{
+       struct wpa_supplicant *wpa_s = _wpa_s;
+
+       return wpa_drv_set_secure_ranging_ctx(wpa_s, own_addr, peer_addr, 0, 0,
+                                             NULL, ltf_keyseed_len,
+                                             ltf_keyseed, 0);
+}
+#endif /* CONFIG_PASN */
+
+
 int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
 {
 #ifndef CONFIG_NO_WPA
@@ -1447,6 +1462,9 @@ int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
        ctx->channel_info = wpa_supplicant_channel_info;
        ctx->transition_disable = wpa_supplicant_transition_disable;
        ctx->store_ptk = wpa_supplicant_store_ptk;
+#ifdef CONFIG_PASN
+       ctx->set_ltf_keyseed = wpa_supplicant_set_ltf_keyseed;
+#endif /* CONFIG_PASN */
 
        wpa_s->wpa = wpa_sm_init(ctx);
        if (wpa_s->wpa == NULL) {