LCOV - code coverage report
Current view: top level - wpa_supplicant - wps_supplicant.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1401264779 Lines: 1169 1430 81.7 %
Date: 2014-05-28 Functions: 74 78 94.9 %

          Line data    Source code
       1             : /*
       2             :  * wpa_supplicant / WPS integration
       3             :  * Copyright (c) 2008-2014, Jouni Malinen <j@w1.fi>
       4             :  *
       5             :  * This software may be distributed under the terms of the BSD license.
       6             :  * See README for more details.
       7             :  */
       8             : 
       9             : #include "includes.h"
      10             : 
      11             : #include "common.h"
      12             : #include "eloop.h"
      13             : #include "uuid.h"
      14             : #include "crypto/random.h"
      15             : #include "crypto/dh_group5.h"
      16             : #include "common/ieee802_11_defs.h"
      17             : #include "common/ieee802_11_common.h"
      18             : #include "common/wpa_common.h"
      19             : #include "common/wpa_ctrl.h"
      20             : #include "eap_common/eap_wsc_common.h"
      21             : #include "eap_peer/eap.h"
      22             : #include "eapol_supp/eapol_supp_sm.h"
      23             : #include "rsn_supp/wpa.h"
      24             : #include "wps/wps_attr_parse.h"
      25             : #include "config.h"
      26             : #include "wpa_supplicant_i.h"
      27             : #include "driver_i.h"
      28             : #include "notify.h"
      29             : #include "blacklist.h"
      30             : #include "bss.h"
      31             : #include "scan.h"
      32             : #include "ap.h"
      33             : #include "p2p/p2p.h"
      34             : #include "p2p_supplicant.h"
      35             : #include "wps_supplicant.h"
      36             : 
      37             : 
      38             : #ifndef WPS_PIN_SCAN_IGNORE_SEL_REG
      39             : #define WPS_PIN_SCAN_IGNORE_SEL_REG 3
      40             : #endif /* WPS_PIN_SCAN_IGNORE_SEL_REG */
      41             : 
      42             : static void wpas_wps_timeout(void *eloop_ctx, void *timeout_ctx);
      43             : static void wpas_clear_wps(struct wpa_supplicant *wpa_s);
      44             : 
      45             : 
      46        3100 : static void wpas_wps_clear_ap_info(struct wpa_supplicant *wpa_s)
      47             : {
      48        3100 :         os_free(wpa_s->wps_ap);
      49        3100 :         wpa_s->wps_ap = NULL;
      50        3100 :         wpa_s->num_wps_ap = 0;
      51        3100 :         wpa_s->wps_ap_iter = 0;
      52        3100 : }
      53             : 
      54             : 
      55         163 : static void wpas_wps_assoc_with_cred(void *eloop_ctx, void *timeout_ctx)
      56             : {
      57         163 :         struct wpa_supplicant *wpa_s = eloop_ctx;
      58         163 :         int use_fast_assoc = timeout_ctx != NULL;
      59             : 
      60         163 :         wpa_printf(MSG_DEBUG, "WPS: Continuing association after eapol_cb");
      61         314 :         if (!use_fast_assoc ||
      62         151 :             wpa_supplicant_fast_associate(wpa_s) != 1)
      63          12 :                 wpa_supplicant_req_scan(wpa_s, 0, 0);
      64         163 : }
      65             : 
      66             : 
      67         241 : static void wpas_wps_assoc_with_cred_cancel(struct wpa_supplicant *wpa_s)
      68             : {
      69         241 :         eloop_cancel_timeout(wpas_wps_assoc_with_cred, wpa_s, (void *) 0);
      70         241 :         eloop_cancel_timeout(wpas_wps_assoc_with_cred, wpa_s, (void *) 1);
      71         241 : }
      72             : 
      73             : 
      74         886 : int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s)
      75             : {
      76             : #ifdef CONFIG_P2P
      77         886 :         if (wpas_p2p_wps_eapol_cb(wpa_s) > 0)
      78           2 :                 return 1;
      79             : #endif /* CONFIG_P2P */
      80             : 
      81        1065 :         if (!wpa_s->wps_success &&
      82         362 :             wpa_s->current_ssid &&
      83         181 :             eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
      84           8 :                 const u8 *bssid = wpa_s->bssid;
      85           8 :                 if (is_zero_ether_addr(bssid))
      86           0 :                         bssid = wpa_s->pending_bssid;
      87             : 
      88          48 :                 wpa_printf(MSG_DEBUG, "WPS: PIN registration with " MACSTR
      89             :                            " did not succeed - continue trying to find "
      90          48 :                            "suitable AP", MAC2STR(bssid));
      91           8 :                 wpa_blacklist_add(wpa_s, bssid);
      92             : 
      93           8 :                 wpa_supplicant_deauthenticate(wpa_s,
      94             :                                               WLAN_REASON_DEAUTH_LEAVING);
      95           8 :                 wpa_s->reassociate = 1;
      96           8 :                 wpa_supplicant_req_scan(wpa_s,
      97           8 :                                         wpa_s->blacklist_cleared ? 5 : 0, 0);
      98           8 :                 wpa_s->blacklist_cleared = 0;
      99           8 :                 return 1;
     100             :         }
     101             : 
     102         876 :         wpas_wps_clear_ap_info(wpa_s);
     103         876 :         eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL);
     104         876 :         if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS && !wpa_s->wps_success)
     105          36 :                 wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_FAIL);
     106             : 
     107        1060 :         if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS && wpa_s->current_ssid &&
     108         184 :             !(wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
     109         163 :                 int disabled = wpa_s->current_ssid->disabled;
     110         163 :                 unsigned int freq = wpa_s->assoc_freq;
     111             :                 struct wpa_bss *bss;
     112         163 :                 struct wpa_ssid *ssid = NULL;
     113         163 :                 int use_fast_assoc = 0;
     114             : 
     115         163 :                 wpa_printf(MSG_DEBUG, "WPS: Network configuration replaced - "
     116             :                            "try to associate with the received credential "
     117             :                            "(freq=%u)", freq);
     118         163 :                 wpa_supplicant_deauthenticate(wpa_s,
     119             :                                               WLAN_REASON_DEAUTH_LEAVING);
     120         163 :                 if (disabled) {
     121           0 :                         wpa_printf(MSG_DEBUG, "WPS: Current network is "
     122             :                                    "disabled - wait for user to enable");
     123           0 :                         return 1;
     124             :                 }
     125         163 :                 wpa_s->after_wps = 5;
     126         163 :                 wpa_s->wps_freq = freq;
     127         163 :                 wpa_s->normal_scans = 0;
     128         163 :                 wpa_s->reassociate = 1;
     129             : 
     130         163 :                 wpa_printf(MSG_DEBUG, "WPS: Checking whether fast association "
     131             :                            "without a new scan can be used");
     132         163 :                 bss = wpa_supplicant_pick_network(wpa_s, &ssid);
     133         163 :                 if (bss) {
     134             :                         struct wpabuf *wps;
     135             :                         struct wps_parse_attr attr;
     136             : 
     137         151 :                         wps = wpa_bss_get_vendor_ie_multi(bss,
     138             :                                                           WPS_IE_VENDOR_TYPE);
     139         302 :                         if (wps && wps_parse_msg(wps, &attr) == 0 &&
     140         302 :                             attr.wps_state &&
     141         151 :                             *attr.wps_state == WPS_STATE_CONFIGURED)
     142         151 :                                 use_fast_assoc = 1;
     143         151 :                         wpabuf_free(wps);
     144             :                 }
     145             : 
     146             :                 /*
     147             :                  * Complete the next step from an eloop timeout to allow pending
     148             :                  * driver events related to the disconnection to be processed
     149             :                  * first. This makes it less likely for disconnection event to
     150             :                  * cause problems with the following connection.
     151             :                  */
     152         163 :                 wpa_printf(MSG_DEBUG, "WPS: Continue association from timeout");
     153         163 :                 wpas_wps_assoc_with_cred_cancel(wpa_s);
     154         163 :                 eloop_register_timeout(0, 10000,
     155             :                                        wpas_wps_assoc_with_cred, wpa_s,
     156             :                                        use_fast_assoc ? (void *) 1 :
     157             :                                        (void *) 0);
     158         163 :                 return 1;
     159             :         }
     160             : 
     161         713 :         if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS && wpa_s->current_ssid) {
     162          21 :                 wpa_printf(MSG_DEBUG, "WPS: Registration completed - waiting "
     163             :                            "for external credential processing");
     164          21 :                 wpas_clear_wps(wpa_s);
     165          21 :                 wpa_supplicant_deauthenticate(wpa_s,
     166             :                                               WLAN_REASON_DEAUTH_LEAVING);
     167          21 :                 return 1;
     168             :         }
     169             : 
     170         692 :         return 0;
     171             : }
     172             : 
     173             : 
     174         169 : static void wpas_wps_security_workaround(struct wpa_supplicant *wpa_s,
     175             :                                          struct wpa_ssid *ssid,
     176             :                                          const struct wps_credential *cred)
     177             : {
     178             :         struct wpa_driver_capa capa;
     179             :         struct wpa_bss *bss;
     180             :         const u8 *ie;
     181             :         struct wpa_ie_data adv;
     182         169 :         int wpa2 = 0, ccmp = 0;
     183             : 
     184             :         /*
     185             :          * Many existing WPS APs do not know how to negotiate WPA2 or CCMP in
     186             :          * case they are configured for mixed mode operation (WPA+WPA2 and
     187             :          * TKIP+CCMP). Try to use scan results to figure out whether the AP
     188             :          * actually supports stronger security and select that if the client
     189             :          * has support for it, too.
     190             :          */
     191             : 
     192         169 :         if (wpa_drv_get_capa(wpa_s, &capa))
     193         152 :                 return; /* Unknown what driver supports */
     194             : 
     195         169 :         if (ssid->ssid == NULL)
     196           0 :                 return;
     197         169 :         bss = wpa_bss_get(wpa_s, cred->mac_addr, ssid->ssid, ssid->ssid_len);
     198         169 :         if (bss == NULL) {
     199         152 :                 wpa_printf(MSG_DEBUG, "WPS: The AP was not found from BSS "
     200             :                            "table - use credential as-is");
     201         152 :                 return;
     202             :         }
     203             : 
     204          17 :         wpa_printf(MSG_DEBUG, "WPS: AP found from BSS table");
     205             : 
     206          17 :         ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
     207          17 :         if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &adv) == 0) {
     208          16 :                 wpa2 = 1;
     209          32 :                 if (adv.pairwise_cipher & WPA_CIPHER_CCMP)
     210          16 :                         ccmp = 1;
     211             :         } else {
     212           1 :                 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
     213           1 :                 if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &adv) == 0 &&
     214           0 :                     adv.pairwise_cipher & WPA_CIPHER_CCMP)
     215           0 :                         ccmp = 1;
     216             :         }
     217             : 
     218          17 :         if (ie == NULL && (ssid->proto & WPA_PROTO_WPA) &&
     219           0 :             (ssid->pairwise_cipher & WPA_CIPHER_TKIP)) {
     220             :                 /*
     221             :                  * TODO: This could be the initial AP configuration and the
     222             :                  * Beacon contents could change shortly. Should request a new
     223             :                  * scan and delay addition of the network until the updated
     224             :                  * scan results are available.
     225             :                  */
     226           0 :                 wpa_printf(MSG_DEBUG, "WPS: The AP did not yet advertise WPA "
     227             :                            "support - use credential as-is");
     228           0 :                 return;
     229             :         }
     230             : 
     231          17 :         if (ccmp && !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) &&
     232           0 :             (ssid->pairwise_cipher & WPA_CIPHER_TKIP) &&
     233           0 :             (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
     234           0 :                 wpa_printf(MSG_DEBUG, "WPS: Add CCMP into the credential "
     235             :                            "based on scan results");
     236           0 :                 if (wpa_s->conf->ap_scan == 1)
     237           0 :                         ssid->pairwise_cipher |= WPA_CIPHER_CCMP;
     238             :                 else
     239           0 :                         ssid->pairwise_cipher = WPA_CIPHER_CCMP;
     240             :         }
     241             : 
     242          17 :         if (wpa2 && !(ssid->proto & WPA_PROTO_RSN) &&
     243           0 :             (ssid->proto & WPA_PROTO_WPA) &&
     244           0 :             (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP)) {
     245           0 :                 wpa_printf(MSG_DEBUG, "WPS: Add WPA2 into the credential "
     246             :                            "based on scan results");
     247           0 :                 if (wpa_s->conf->ap_scan == 1)
     248           0 :                         ssid->proto |= WPA_PROTO_RSN;
     249             :                 else
     250           0 :                         ssid->proto = WPA_PROTO_RSN;
     251             :         }
     252             : }
     253             : 
     254             : 
     255         169 : static void wpas_wps_remove_dup_network(struct wpa_supplicant *wpa_s,
     256             :                                         struct wpa_ssid *new_ssid)
     257             : {
     258             :         struct wpa_ssid *ssid, *next;
     259             : 
     260         513 :         for (ssid = wpa_s->conf->ssid, next = ssid ? ssid->next : NULL; ssid;
     261         175 :              ssid = next, next = ssid ? ssid->next : NULL) {
     262             :                 /*
     263             :                  * new_ssid has already been added to the list in
     264             :                  * wpas_wps_add_network(), so skip it.
     265             :                  */
     266         175 :                 if (ssid == new_ssid)
     267         169 :                         continue;
     268             : 
     269           6 :                 if (ssid->bssid_set || new_ssid->bssid_set) {
     270           3 :                         if (ssid->bssid_set != new_ssid->bssid_set)
     271           2 :                                 continue;
     272           1 :                         if (os_memcmp(ssid->bssid, new_ssid->bssid, ETH_ALEN) !=
     273             :                             0)
     274           0 :                                 continue;
     275             :                 }
     276             : 
     277             :                 /* compare SSID */
     278           4 :                 if (ssid->ssid_len == 0 || ssid->ssid_len != new_ssid->ssid_len)
     279           1 :                         continue;
     280             : 
     281           3 :                 if (ssid->ssid && new_ssid->ssid) {
     282           6 :                         if (os_memcmp(ssid->ssid, new_ssid->ssid,
     283             :                                       ssid->ssid_len) != 0)
     284           0 :                                 continue;
     285           0 :                 } else if (ssid->ssid || new_ssid->ssid)
     286           0 :                         continue;
     287             : 
     288             :                 /* compare security parameters */
     289           5 :                 if (ssid->auth_alg != new_ssid->auth_alg ||
     290           4 :                     ssid->key_mgmt != new_ssid->key_mgmt ||
     291           4 :                     ssid->proto != new_ssid->proto ||
     292           4 :                     ssid->pairwise_cipher != new_ssid->pairwise_cipher ||
     293           2 :                     ssid->group_cipher != new_ssid->group_cipher)
     294           1 :                         continue;
     295             : 
     296             :                 /* Remove the duplicated older network entry. */
     297           2 :                 wpa_printf(MSG_DEBUG, "Remove duplicate network %d", ssid->id);
     298           2 :                 wpas_notify_network_removed(wpa_s, ssid);
     299           2 :                 wpa_config_remove_network(wpa_s->conf, ssid->id);
     300             :         }
     301         169 : }
     302             : 
     303             : 
     304         169 : static int wpa_supplicant_wps_cred(void *ctx,
     305             :                                    const struct wps_credential *cred)
     306             : {
     307         169 :         struct wpa_supplicant *wpa_s = ctx;
     308         169 :         struct wpa_ssid *ssid = wpa_s->current_ssid;
     309             :         u16 auth_type;
     310             : #ifdef CONFIG_WPS_REG_DISABLE_OPEN
     311             :         int registrar = 0;
     312             : #endif /* CONFIG_WPS_REG_DISABLE_OPEN */
     313             : 
     314         338 :         if ((wpa_s->conf->wps_cred_processing == 1 ||
     315         171 :              wpa_s->conf->wps_cred_processing == 2) && cred->cred_attr) {
     316           1 :                 size_t blen = cred->cred_attr_len * 2 + 1;
     317           1 :                 char *buf = os_malloc(blen);
     318           1 :                 if (buf) {
     319           1 :                         wpa_snprintf_hex(buf, blen,
     320             :                                          cred->cred_attr, cred->cred_attr_len);
     321           1 :                         wpa_msg(wpa_s, MSG_INFO, "%s%s",
     322             :                                 WPS_EVENT_CRED_RECEIVED, buf);
     323           1 :                         os_free(buf);
     324             :                 }
     325             : 
     326           1 :                 wpas_notify_wps_credential(wpa_s, cred);
     327             :         } else
     328         168 :                 wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_CRED_RECEIVED);
     329             : 
     330         338 :         wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute",
     331         169 :                         cred->cred_attr, cred->cred_attr_len);
     332             : 
     333         169 :         if (wpa_s->conf->wps_cred_processing == 1)
     334           0 :                 return 0;
     335             : 
     336         169 :         wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID", cred->ssid, cred->ssid_len);
     337         169 :         wpa_printf(MSG_DEBUG, "WPS: Authentication Type 0x%x",
     338         169 :                    cred->auth_type);
     339         169 :         wpa_printf(MSG_DEBUG, "WPS: Encryption Type 0x%x", cred->encr_type);
     340         169 :         wpa_printf(MSG_DEBUG, "WPS: Network Key Index %d", cred->key_idx);
     341         338 :         wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key",
     342         169 :                         cred->key, cred->key_len);
     343        1014 :         wpa_printf(MSG_DEBUG, "WPS: MAC Address " MACSTR,
     344        1014 :                    MAC2STR(cred->mac_addr));
     345             : 
     346         169 :         auth_type = cred->auth_type;
     347         169 :         if (auth_type == (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) {
     348           0 :                 wpa_printf(MSG_DEBUG, "WPS: Workaround - convert mixed-mode "
     349             :                            "auth_type into WPA2PSK");
     350           0 :                 auth_type = WPS_AUTH_WPA2PSK;
     351             :         }
     352             : 
     353         169 :         if (auth_type != WPS_AUTH_OPEN &&
     354         167 :             auth_type != WPS_AUTH_WPAPSK &&
     355             :             auth_type != WPS_AUTH_WPA2PSK) {
     356           0 :                 wpa_printf(MSG_DEBUG, "WPS: Ignored credentials for "
     357             :                            "unsupported authentication type 0x%x",
     358             :                            auth_type);
     359           0 :                 return 0;
     360             :         }
     361             : 
     362         169 :         if (auth_type == WPS_AUTH_WPAPSK || auth_type == WPS_AUTH_WPA2PSK) {
     363         168 :                 if (cred->key_len < 8 || cred->key_len > 2 * PMK_LEN) {
     364           0 :                         wpa_printf(MSG_ERROR, "WPS: Reject PSK credential with "
     365             :                                    "invalid Network Key length %lu",
     366             :                                    (unsigned long) cred->key_len);
     367           0 :                         return -1;
     368             :                 }
     369             :         }
     370             : 
     371         169 :         if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
     372         163 :                 wpa_printf(MSG_DEBUG, "WPS: Replace WPS network block based "
     373             :                            "on the received credential");
     374             : #ifdef CONFIG_WPS_REG_DISABLE_OPEN
     375             :                 if (ssid->eap.identity &&
     376             :                     ssid->eap.identity_len == WSC_ID_REGISTRAR_LEN &&
     377             :                     os_memcmp(ssid->eap.identity, WSC_ID_REGISTRAR,
     378             :                               WSC_ID_REGISTRAR_LEN) == 0)
     379             :                         registrar = 1;
     380             : #endif /* CONFIG_WPS_REG_DISABLE_OPEN */
     381         163 :                 os_free(ssid->eap.identity);
     382         163 :                 ssid->eap.identity = NULL;
     383         163 :                 ssid->eap.identity_len = 0;
     384         163 :                 os_free(ssid->eap.phase1);
     385         163 :                 ssid->eap.phase1 = NULL;
     386         163 :                 os_free(ssid->eap.eap_methods);
     387         163 :                 ssid->eap.eap_methods = NULL;
     388         163 :                 if (!ssid->p2p_group) {
     389          65 :                         ssid->temporary = 0;
     390          65 :                         ssid->bssid_set = 0;
     391             :                 }
     392         163 :                 ssid->disabled_until.sec = 0;
     393         163 :                 ssid->disabled_until.usec = 0;
     394         163 :                 ssid->auth_failures = 0;
     395             :         } else {
     396           6 :                 wpa_printf(MSG_DEBUG, "WPS: Create a new network based on the "
     397             :                            "received credential");
     398           6 :                 ssid = wpa_config_add_network(wpa_s->conf);
     399           6 :                 if (ssid == NULL)
     400           0 :                         return -1;
     401           6 :                 if (wpa_s->current_ssid) {
     402             :                         /*
     403             :                          * Should the GO issue multiple credentials for some
     404             :                          * reason, each credential should be marked as a
     405             :                          * temporary P2P group similarly to the one that gets
     406             :                          * marked as such based on the pre-configured values
     407             :                          * used for the WPS network block.
     408             :                          */
     409           2 :                         ssid->p2p_group = wpa_s->current_ssid->p2p_group;
     410           2 :                         ssid->temporary = wpa_s->current_ssid->temporary;
     411             :                 }
     412           6 :                 wpas_notify_network_added(wpa_s, ssid);
     413             :         }
     414             : 
     415         169 :         wpa_config_set_network_defaults(ssid);
     416             : 
     417         169 :         os_free(ssid->ssid);
     418         169 :         ssid->ssid = os_malloc(cred->ssid_len);
     419         169 :         if (ssid->ssid) {
     420         169 :                 os_memcpy(ssid->ssid, cred->ssid, cred->ssid_len);
     421         169 :                 ssid->ssid_len = cred->ssid_len;
     422             :         }
     423             : 
     424         169 :         switch (cred->encr_type) {
     425             :         case WPS_ENCR_NONE:
     426           1 :                 break;
     427             :         case WPS_ENCR_TKIP:
     428           1 :                 ssid->pairwise_cipher = WPA_CIPHER_TKIP;
     429           1 :                 break;
     430             :         case WPS_ENCR_AES:
     431         167 :                 ssid->pairwise_cipher = WPA_CIPHER_CCMP;
     432         167 :                 break;
     433             :         }
     434             : 
     435         169 :         switch (auth_type) {
     436             :         case WPS_AUTH_OPEN:
     437           1 :                 ssid->auth_alg = WPA_AUTH_ALG_OPEN;
     438           1 :                 ssid->key_mgmt = WPA_KEY_MGMT_NONE;
     439           1 :                 ssid->proto = 0;
     440             : #ifdef CONFIG_WPS_REG_DISABLE_OPEN
     441             :                 if (registrar) {
     442             :                         wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_OPEN_NETWORK
     443             :                                 "id=%d - Credentials for an open "
     444             :                                 "network disabled by default - use "
     445             :                                 "'select_network %d' to enable",
     446             :                                 ssid->id, ssid->id);
     447             :                         ssid->disabled = 1;
     448             :                 }
     449             : #endif /* CONFIG_WPS_REG_DISABLE_OPEN */
     450           1 :                 break;
     451             :         case WPS_AUTH_WPAPSK:
     452           1 :                 ssid->auth_alg = WPA_AUTH_ALG_OPEN;
     453           1 :                 ssid->key_mgmt = WPA_KEY_MGMT_PSK;
     454           1 :                 ssid->proto = WPA_PROTO_WPA;
     455           1 :                 break;
     456             :         case WPS_AUTH_WPA2PSK:
     457         167 :                 ssid->auth_alg = WPA_AUTH_ALG_OPEN;
     458         167 :                 ssid->key_mgmt = WPA_KEY_MGMT_PSK;
     459         167 :                 ssid->proto = WPA_PROTO_RSN;
     460         167 :                 break;
     461             :         }
     462             : 
     463         169 :         if (ssid->key_mgmt == WPA_KEY_MGMT_PSK) {
     464         168 :                 if (cred->key_len == 2 * PMK_LEN) {
     465         113 :                         if (hexstr2bin((const char *) cred->key, ssid->psk,
     466             :                                        PMK_LEN)) {
     467           0 :                                 wpa_printf(MSG_ERROR, "WPS: Invalid Network "
     468             :                                            "Key");
     469           0 :                                 return -1;
     470             :                         }
     471         113 :                         ssid->psk_set = 1;
     472         113 :                         ssid->export_keys = 1;
     473          55 :                 } else if (cred->key_len >= 8 && cred->key_len < 2 * PMK_LEN) {
     474          55 :                         os_free(ssid->passphrase);
     475          55 :                         ssid->passphrase = os_malloc(cred->key_len + 1);
     476          55 :                         if (ssid->passphrase == NULL)
     477           0 :                                 return -1;
     478          55 :                         os_memcpy(ssid->passphrase, cred->key, cred->key_len);
     479          55 :                         ssid->passphrase[cred->key_len] = '\0';
     480          55 :                         wpa_config_update_psk(ssid);
     481          55 :                         ssid->export_keys = 1;
     482             :                 } else {
     483           0 :                         wpa_printf(MSG_ERROR, "WPS: Invalid Network Key "
     484             :                                    "length %lu",
     485             :                                    (unsigned long) cred->key_len);
     486           0 :                         return -1;
     487             :                 }
     488             :         }
     489             : 
     490         169 :         wpas_wps_security_workaround(wpa_s, ssid, cred);
     491             : 
     492         169 :         wpas_wps_remove_dup_network(wpa_s, ssid);
     493             : 
     494             : #ifndef CONFIG_NO_CONFIG_WRITE
     495         169 :         if (wpa_s->conf->update_config &&
     496           0 :             wpa_config_write(wpa_s->confname, wpa_s->conf)) {
     497           0 :                 wpa_printf(MSG_DEBUG, "WPS: Failed to update configuration");
     498           0 :                 return -1;
     499             :         }
     500             : #endif /* CONFIG_NO_CONFIG_WRITE */
     501             : 
     502             :         /*
     503             :          * Optimize the post-WPS scan based on the channel used during
     504             :          * the provisioning in case EAP-Failure is not received.
     505             :          */
     506         169 :         wpa_s->after_wps = 5;
     507         169 :         wpa_s->wps_freq = wpa_s->assoc_freq;
     508             : 
     509         169 :         return 0;
     510             : }
     511             : 
     512             : 
     513          20 : static void wpa_supplicant_wps_event_m2d(struct wpa_supplicant *wpa_s,
     514             :                                          struct wps_event_m2d *m2d)
     515             : {
     516          40 :         wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_M2D
     517             :                 "dev_password_id=%d config_error=%d",
     518          40 :                 m2d->dev_password_id, m2d->config_error);
     519          20 :         wpas_notify_wps_event_m2d(wpa_s, m2d);
     520             : #ifdef CONFIG_P2P
     521          20 :         if (wpa_s->parent && wpa_s->parent != wpa_s) {
     522           4 :                 wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_M2D
     523             :                         "dev_password_id=%d config_error=%d",
     524           4 :                         m2d->dev_password_id, m2d->config_error);
     525             :         }
     526          20 :         if (m2d->config_error == WPS_CFG_MULTIPLE_PBC_DETECTED) {
     527             :                 /*
     528             :                  * Notify P2P from eloop timeout to avoid issues with the
     529             :                  * interface getting removed while processing a message.
     530             :                  */
     531           3 :                 eloop_register_timeout(0, 0, wpas_p2p_pbc_overlap_cb, wpa_s,
     532             :                                        NULL);
     533             :         }
     534             : #endif /* CONFIG_P2P */
     535          20 : }
     536             : 
     537             : 
     538          17 : static void wpas_wps_clear_timeout(void *eloop_ctx, void *timeout_ctx)
     539             : {
     540          17 :         struct wpa_supplicant *wpa_s = eloop_ctx;
     541          17 :         wpa_printf(MSG_DEBUG, "WPS: Clear WPS network from timeout");
     542          17 :         wpas_clear_wps(wpa_s);
     543          17 : }
     544             : 
     545             : 
     546          39 : static void wpa_supplicant_wps_event_fail(struct wpa_supplicant *wpa_s,
     547             :                                           struct wps_event_fail *fail)
     548             : {
     549          40 :         if (fail->error_indication > 0 &&
     550           1 :             fail->error_indication < NUM_WPS_EI_VALUES) {
     551           3 :                 wpa_msg(wpa_s, MSG_INFO,
     552             :                         WPS_EVENT_FAIL "msg=%d config_error=%d reason=%d (%s)",
     553           2 :                         fail->msg, fail->config_error, fail->error_indication,
     554           1 :                         wps_ei_str(fail->error_indication));
     555           2 :                 if (wpa_s->parent && wpa_s->parent != wpa_s)
     556           0 :                         wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_FAIL
     557             :                                 "msg=%d config_error=%d reason=%d (%s)",
     558           0 :                                 fail->msg, fail->config_error,
     559           0 :                                 fail->error_indication,
     560           0 :                                 wps_ei_str(fail->error_indication));
     561             :         } else {
     562          38 :                 wpa_msg(wpa_s, MSG_INFO,
     563             :                         WPS_EVENT_FAIL "msg=%d config_error=%d",
     564          38 :                         fail->msg, fail->config_error);
     565          38 :                 if (wpa_s->parent && wpa_s->parent != wpa_s)
     566           1 :                         wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_FAIL
     567             :                                 "msg=%d config_error=%d",
     568           1 :                                 fail->msg, fail->config_error);
     569             :         }
     570             : 
     571             :         /*
     572             :          * Need to allow WPS processing to complete, e.g., by sending WSC_NACK.
     573             :          */
     574          39 :         wpa_printf(MSG_DEBUG, "WPS: Register timeout to clear WPS network");
     575          39 :         eloop_cancel_timeout(wpas_wps_clear_timeout, wpa_s, NULL);
     576          39 :         eloop_register_timeout(0, 100000, wpas_wps_clear_timeout, wpa_s, NULL);
     577             : 
     578          39 :         wpas_notify_wps_event_fail(wpa_s, fail);
     579             : #ifdef CONFIG_P2P
     580          39 :         wpas_p2p_wps_failed(wpa_s, fail);
     581             : #endif /* CONFIG_P2P */
     582          39 : }
     583             : 
     584             : 
     585             : static void wpas_wps_reenable_networks_cb(void *eloop_ctx, void *timeout_ctx);
     586             : 
     587        2149 : static void wpas_wps_reenable_networks(struct wpa_supplicant *wpa_s)
     588             : {
     589             :         struct wpa_ssid *ssid;
     590        2149 :         int changed = 0;
     591             : 
     592        2149 :         eloop_cancel_timeout(wpas_wps_reenable_networks_cb, wpa_s, NULL);
     593             : 
     594        2735 :         for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
     595         586 :                 if (ssid->disabled_for_connect && ssid->disabled) {
     596           2 :                         ssid->disabled_for_connect = 0;
     597           2 :                         ssid->disabled = 0;
     598           2 :                         wpas_notify_network_enabled_changed(wpa_s, ssid);
     599           2 :                         changed++;
     600             :                 }
     601             :         }
     602             : 
     603        2149 :         if (changed) {
     604             : #ifndef CONFIG_NO_CONFIG_WRITE
     605           1 :                 if (wpa_s->conf->update_config &&
     606           0 :                     wpa_config_write(wpa_s->confname, wpa_s->conf)) {
     607           0 :                         wpa_printf(MSG_DEBUG, "WPS: Failed to update "
     608             :                                    "configuration");
     609             :                 }
     610             : #endif /* CONFIG_NO_CONFIG_WRITE */
     611             :         }
     612        2149 : }
     613             : 
     614             : 
     615           3 : static void wpas_wps_reenable_networks_cb(void *eloop_ctx, void *timeout_ctx)
     616             : {
     617           3 :         struct wpa_supplicant *wpa_s = eloop_ctx;
     618             :         /* Enable the networks disabled during wpas_wps_reassoc */
     619           3 :         wpas_wps_reenable_networks(wpa_s);
     620           3 : }
     621             : 
     622             : 
     623         155 : static void wpa_supplicant_wps_event_success(struct wpa_supplicant *wpa_s)
     624             : {
     625         155 :         wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_SUCCESS);
     626         155 :         wpa_s->wps_success = 1;
     627         155 :         wpas_notify_wps_event_success(wpa_s);
     628         155 :         if (wpa_s->current_ssid)
     629         155 :                 wpas_clear_temp_disabled(wpa_s, wpa_s->current_ssid, 1);
     630         155 :         wpa_s->extra_blacklist_count = 0;
     631             : 
     632             :         /*
     633             :          * Enable the networks disabled during wpas_wps_reassoc after 10
     634             :          * seconds. The 10 seconds timer is to allow the data connection to be
     635             :          * formed before allowing other networks to be selected.
     636             :          */
     637         155 :         eloop_register_timeout(10, 0, wpas_wps_reenable_networks_cb, wpa_s,
     638             :                                NULL);
     639             : 
     640             : #ifdef CONFIG_P2P
     641         155 :         wpas_p2p_wps_success(wpa_s, wpa_s->bssid, 0);
     642             : #endif /* CONFIG_P2P */
     643         155 : }
     644             : 
     645             : 
     646           9 : static void wpa_supplicant_wps_event_er_ap_add(struct wpa_supplicant *wpa_s,
     647             :                                                struct wps_event_er_ap *ap)
     648             : {
     649             :         char uuid_str[100];
     650             :         char dev_type[WPS_DEV_TYPE_BUFSIZE];
     651             : 
     652           9 :         uuid_bin2str(ap->uuid, uuid_str, sizeof(uuid_str));
     653           9 :         if (ap->pri_dev_type)
     654           9 :                 wps_dev_type_bin2str(ap->pri_dev_type, dev_type,
     655             :                                      sizeof(dev_type));
     656             :         else
     657           0 :                 dev_type[0] = '\0';
     658             : 
     659         117 :         wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_ER_AP_ADD "%s " MACSTR
     660             :                 " pri_dev_type=%s wps_state=%d |%s|%s|%s|%s|%s|%s|",
     661          63 :                 uuid_str, MAC2STR(ap->mac_addr), dev_type, ap->wps_state,
     662           9 :                 ap->friendly_name ? ap->friendly_name : "",
     663           9 :                 ap->manufacturer ? ap->manufacturer : "",
     664           9 :                 ap->model_description ? ap->model_description : "",
     665           9 :                 ap->model_name ? ap->model_name : "",
     666           9 :                 ap->manufacturer_url ? ap->manufacturer_url : "",
     667           9 :                 ap->model_url ? ap->model_url : "");
     668           9 : }
     669             : 
     670             : 
     671           9 : static void wpa_supplicant_wps_event_er_ap_remove(struct wpa_supplicant *wpa_s,
     672             :                                                   struct wps_event_er_ap *ap)
     673             : {
     674             :         char uuid_str[100];
     675           9 :         uuid_bin2str(ap->uuid, uuid_str, sizeof(uuid_str));
     676           9 :         wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_ER_AP_REMOVE "%s", uuid_str);
     677           9 : }
     678             : 
     679             : 
     680          26 : static void wpa_supplicant_wps_event_er_enrollee_add(
     681             :         struct wpa_supplicant *wpa_s, struct wps_event_er_enrollee *enrollee)
     682             : {
     683             :         char uuid_str[100];
     684             :         char dev_type[WPS_DEV_TYPE_BUFSIZE];
     685             : 
     686          26 :         uuid_bin2str(enrollee->uuid, uuid_str, sizeof(uuid_str));
     687          26 :         if (enrollee->pri_dev_type)
     688          26 :                 wps_dev_type_bin2str(enrollee->pri_dev_type, dev_type,
     689             :                                      sizeof(dev_type));
     690             :         else
     691           0 :                 dev_type[0] = '\0';
     692             : 
     693         338 :         wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_ER_ENROLLEE_ADD "%s " MACSTR
     694             :                 " M1=%d config_methods=0x%x dev_passwd_id=%d pri_dev_type=%s "
     695             :                 "|%s|%s|%s|%s|%s|",
     696         156 :                 uuid_str, MAC2STR(enrollee->mac_addr), enrollee->m1_received,
     697          52 :                 enrollee->config_methods, enrollee->dev_passwd_id, dev_type,
     698          26 :                 enrollee->dev_name ? enrollee->dev_name : "",
     699          26 :                 enrollee->manufacturer ? enrollee->manufacturer : "",
     700          26 :                 enrollee->model_name ? enrollee->model_name : "",
     701          26 :                 enrollee->model_number ? enrollee->model_number : "",
     702          26 :                 enrollee->serial_number ? enrollee->serial_number : "");
     703          26 : }
     704             : 
     705             : 
     706          18 : static void wpa_supplicant_wps_event_er_enrollee_remove(
     707             :         struct wpa_supplicant *wpa_s, struct wps_event_er_enrollee *enrollee)
     708             : {
     709             :         char uuid_str[100];
     710          18 :         uuid_bin2str(enrollee->uuid, uuid_str, sizeof(uuid_str));
     711         108 :         wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_ER_ENROLLEE_REMOVE "%s " MACSTR,
     712         108 :                 uuid_str, MAC2STR(enrollee->mac_addr));
     713          18 : }
     714             : 
     715             : 
     716           1 : static void wpa_supplicant_wps_event_er_ap_settings(
     717             :         struct wpa_supplicant *wpa_s,
     718             :         struct wps_event_er_ap_settings *ap_settings)
     719             : {
     720             :         char uuid_str[100];
     721             :         char key_str[65];
     722           1 :         const struct wps_credential *cred = ap_settings->cred;
     723             : 
     724           1 :         key_str[0] = '\0';
     725           1 :         if (cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) {
     726           1 :                 if (cred->key_len >= 8 && cred->key_len <= 64) {
     727           1 :                         os_memcpy(key_str, cred->key, cred->key_len);
     728           1 :                         key_str[cred->key_len] = '\0';
     729             :                 }
     730             :         }
     731             : 
     732           1 :         uuid_bin2str(ap_settings->uuid, uuid_str, sizeof(uuid_str));
     733             :         /* Use wpa_msg_ctrl to avoid showing the key in debug log */
     734           3 :         wpa_msg_ctrl(wpa_s, MSG_INFO, WPS_EVENT_ER_AP_SETTINGS
     735             :                      "uuid=%s ssid=%s auth_type=0x%04x encr_type=0x%04x "
     736             :                      "key=%s",
     737           1 :                      uuid_str, wpa_ssid_txt(cred->ssid, cred->ssid_len),
     738           2 :                      cred->auth_type, cred->encr_type, key_str);
     739           1 : }
     740             : 
     741             : 
     742          44 : static void wpa_supplicant_wps_event_er_set_sel_reg(
     743             :         struct wpa_supplicant *wpa_s,
     744             :         struct wps_event_er_set_selected_registrar *ev)
     745             : {
     746             :         char uuid_str[100];
     747             : 
     748          44 :         uuid_bin2str(ev->uuid, uuid_str, sizeof(uuid_str));
     749          44 :         switch (ev->state) {
     750             :         case WPS_ER_SET_SEL_REG_START:
     751          52 :                 wpa_msg(wpa_s, MSG_DEBUG, WPS_EVENT_ER_SET_SEL_REG
     752             :                         "uuid=%s state=START sel_reg=%d dev_passwd_id=%u "
     753             :                         "sel_reg_config_methods=0x%x",
     754          26 :                         uuid_str, ev->sel_reg, ev->dev_passwd_id,
     755          26 :                         ev->sel_reg_config_methods);
     756          26 :                 break;
     757             :         case WPS_ER_SET_SEL_REG_DONE:
     758          18 :                 wpa_msg(wpa_s, MSG_DEBUG, WPS_EVENT_ER_SET_SEL_REG
     759             :                         "uuid=%s state=DONE", uuid_str);
     760          18 :                 break;
     761             :         case WPS_ER_SET_SEL_REG_FAILED:
     762           0 :                 wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_ER_SET_SEL_REG
     763             :                         "uuid=%s state=FAILED", uuid_str);
     764           0 :                 break;
     765             :         }
     766          44 : }
     767             : 
     768             : 
     769         327 : static void wpa_supplicant_wps_event(void *ctx, enum wps_event event,
     770             :                                      union wps_event_data *data)
     771             : {
     772         327 :         struct wpa_supplicant *wpa_s = ctx;
     773         327 :         switch (event) {
     774             :         case WPS_EV_M2D:
     775          20 :                 wpa_supplicant_wps_event_m2d(wpa_s, &data->m2d);
     776          20 :                 break;
     777             :         case WPS_EV_FAIL:
     778          39 :                 wpa_supplicant_wps_event_fail(wpa_s, &data->fail);
     779          39 :                 break;
     780             :         case WPS_EV_SUCCESS:
     781         155 :                 wpa_supplicant_wps_event_success(wpa_s);
     782         155 :                 break;
     783             :         case WPS_EV_PWD_AUTH_FAIL:
     784             : #ifdef CONFIG_AP
     785           4 :                 if (wpa_s->ap_iface && data->pwd_auth_fail.enrollee)
     786           0 :                         wpa_supplicant_ap_pwd_auth_fail(wpa_s);
     787             : #endif /* CONFIG_AP */
     788           4 :                 break;
     789             :         case WPS_EV_PBC_OVERLAP:
     790           0 :                 break;
     791             :         case WPS_EV_PBC_TIMEOUT:
     792           0 :                 break;
     793             :         case WPS_EV_PBC_ACTIVE:
     794           1 :                 wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_ACTIVE);
     795           1 :                 break;
     796             :         case WPS_EV_PBC_DISABLE:
     797           1 :                 wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_DISABLE);
     798           1 :                 break;
     799             :         case WPS_EV_ER_AP_ADD:
     800           9 :                 wpa_supplicant_wps_event_er_ap_add(wpa_s, &data->ap);
     801           9 :                 break;
     802             :         case WPS_EV_ER_AP_REMOVE:
     803           9 :                 wpa_supplicant_wps_event_er_ap_remove(wpa_s, &data->ap);
     804           9 :                 break;
     805             :         case WPS_EV_ER_ENROLLEE_ADD:
     806          26 :                 wpa_supplicant_wps_event_er_enrollee_add(wpa_s,
     807             :                                                          &data->enrollee);
     808          26 :                 break;
     809             :         case WPS_EV_ER_ENROLLEE_REMOVE:
     810          18 :                 wpa_supplicant_wps_event_er_enrollee_remove(wpa_s,
     811             :                                                             &data->enrollee);
     812          18 :                 break;
     813             :         case WPS_EV_ER_AP_SETTINGS:
     814           1 :                 wpa_supplicant_wps_event_er_ap_settings(wpa_s,
     815             :                                                         &data->ap_settings);
     816           1 :                 break;
     817             :         case WPS_EV_ER_SET_SELECTED_REGISTRAR:
     818          44 :                 wpa_supplicant_wps_event_er_set_sel_reg(wpa_s,
     819             :                                                         &data->set_sel_reg);
     820          44 :                 break;
     821             :         case WPS_EV_AP_PIN_SUCCESS:
     822           0 :                 break;
     823             :         }
     824         327 : }
     825             : 
     826             : 
     827         210 : static int wpa_supplicant_wps_rf_band(void *ctx)
     828             : {
     829         210 :         struct wpa_supplicant *wpa_s = ctx;
     830             : 
     831         210 :         if (!wpa_s->current_ssid || !wpa_s->assoc_freq)
     832           0 :                 return 0;
     833             : 
     834         210 :         return (wpa_s->assoc_freq > 2484) ? WPS_RF_50GHZ : WPS_RF_24GHZ;
     835             : }
     836             : 
     837             : 
     838         509 : enum wps_request_type wpas_wps_get_req_type(struct wpa_ssid *ssid)
     839             : {
     840         901 :         if (eap_is_wps_pbc_enrollee(&ssid->eap) ||
     841         392 :             eap_is_wps_pin_enrollee(&ssid->eap))
     842         397 :                 return WPS_REQ_ENROLLEE;
     843             :         else
     844         112 :                 return WPS_REQ_REGISTRAR;
     845             : }
     846             : 
     847             : 
     848        1532 : static void wpas_clear_wps(struct wpa_supplicant *wpa_s)
     849             : {
     850             :         int id;
     851        1532 :         struct wpa_ssid *ssid, *remove_ssid = NULL, *prev_current;
     852             : 
     853        1532 :         wpa_s->after_wps = 0;
     854        1532 :         wpa_s->known_wps_freq = 0;
     855             : 
     856        1532 :         prev_current = wpa_s->current_ssid;
     857             : 
     858             :         /* Enable the networks disabled during wpas_wps_reassoc */
     859        1532 :         wpas_wps_reenable_networks(wpa_s);
     860             : 
     861        1532 :         eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL);
     862        1532 :         eloop_cancel_timeout(wpas_wps_clear_timeout, wpa_s, NULL);
     863             : 
     864             :         /* Remove any existing WPS network from configuration */
     865        1532 :         ssid = wpa_s->conf->ssid;
     866        3644 :         while (ssid) {
     867         580 :                 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
     868          30 :                         if (ssid == wpa_s->current_ssid) {
     869          22 :                                 wpa_supplicant_deauthenticate(
     870             :                                         wpa_s, WLAN_REASON_DEAUTH_LEAVING);
     871             :                         }
     872          30 :                         id = ssid->id;
     873          30 :                         remove_ssid = ssid;
     874             :                 } else
     875         550 :                         id = -1;
     876         580 :                 ssid = ssid->next;
     877         580 :                 if (id >= 0) {
     878          30 :                         if (prev_current == remove_ssid) {
     879          22 :                                 wpa_sm_set_config(wpa_s->wpa, NULL);
     880          22 :                                 eapol_sm_notify_config(wpa_s->eapol, NULL,
     881             :                                                        NULL);
     882             :                         }
     883          30 :                         wpas_notify_network_removed(wpa_s, remove_ssid);
     884          30 :                         wpa_config_remove_network(wpa_s->conf, id);
     885             :                 }
     886             :         }
     887             : 
     888        1532 :         wpas_wps_clear_ap_info(wpa_s);
     889        1532 : }
     890             : 
     891             : 
     892           1 : static void wpas_wps_timeout(void *eloop_ctx, void *timeout_ctx)
     893             : {
     894           1 :         struct wpa_supplicant *wpa_s = eloop_ctx;
     895           1 :         wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_TIMEOUT "Requested operation timed "
     896             :                 "out");
     897           1 :         wpas_clear_wps(wpa_s);
     898           1 : }
     899             : 
     900             : 
     901         200 : static struct wpa_ssid * wpas_wps_add_network(struct wpa_supplicant *wpa_s,
     902             :                                               int registrar, const u8 *dev_addr,
     903             :                                               const u8 *bssid)
     904             : {
     905             :         struct wpa_ssid *ssid;
     906             : 
     907         200 :         ssid = wpa_config_add_network(wpa_s->conf);
     908         200 :         if (ssid == NULL)
     909           0 :                 return NULL;
     910         200 :         wpas_notify_network_added(wpa_s, ssid);
     911         200 :         wpa_config_set_network_defaults(ssid);
     912         200 :         ssid->temporary = 1;
     913         400 :         if (wpa_config_set(ssid, "key_mgmt", "WPS", 0) < 0 ||
     914         400 :             wpa_config_set(ssid, "eap", "WSC", 0) < 0 ||
     915         200 :             wpa_config_set(ssid, "identity", registrar ?
     916             :                            "\"" WSC_ID_REGISTRAR "\"" :
     917             :                            "\"" WSC_ID_ENROLLEE "\"", 0) < 0) {
     918           0 :                 wpas_notify_network_removed(wpa_s, ssid);
     919           0 :                 wpa_config_remove_network(wpa_s->conf, ssid->id);
     920           0 :                 return NULL;
     921             :         }
     922             : 
     923             : #ifdef CONFIG_P2P
     924         200 :         if (dev_addr)
     925          14 :                 os_memcpy(ssid->go_p2p_dev_addr, dev_addr, ETH_ALEN);
     926             : #endif /* CONFIG_P2P */
     927             : 
     928         200 :         if (bssid) {
     929             : #ifndef CONFIG_P2P
     930             :                 struct wpa_bss *bss;
     931             :                 int count = 0;
     932             : #endif /* CONFIG_P2P */
     933             : 
     934         150 :                 os_memcpy(ssid->bssid, bssid, ETH_ALEN);
     935         150 :                 ssid->bssid_set = 1;
     936             : 
     937             :                 /*
     938             :                  * Note: With P2P, the SSID may change at the time the WPS
     939             :                  * provisioning is started, so better not filter the AP based
     940             :                  * on the current SSID in the scan results.
     941             :                  */
     942             : #ifndef CONFIG_P2P
     943             :                 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
     944             :                         if (os_memcmp(bssid, bss->bssid, ETH_ALEN) != 0)
     945             :                                 continue;
     946             : 
     947             :                         os_free(ssid->ssid);
     948             :                         ssid->ssid = os_malloc(bss->ssid_len);
     949             :                         if (ssid->ssid == NULL)
     950             :                                 break;
     951             :                         os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len);
     952             :                         ssid->ssid_len = bss->ssid_len;
     953             :                         wpa_hexdump_ascii(MSG_DEBUG, "WPS: Picked SSID from "
     954             :                                           "scan results",
     955             :                                           ssid->ssid, ssid->ssid_len);
     956             :                         count++;
     957             :                 }
     958             : 
     959             :                 if (count > 1) {
     960             :                         wpa_printf(MSG_DEBUG, "WPS: More than one SSID found "
     961             :                                    "for the AP; use wildcard");
     962             :                         os_free(ssid->ssid);
     963             :                         ssid->ssid = NULL;
     964             :                         ssid->ssid_len = 0;
     965             :                 }
     966             : #endif /* CONFIG_P2P */
     967             :         }
     968             : 
     969         200 :         return ssid;
     970             : }
     971             : 
     972             : 
     973         208 : static void wpas_wps_temp_disable(struct wpa_supplicant *wpa_s,
     974             :                                   struct wpa_ssid *selected)
     975             : {
     976             :         struct wpa_ssid *ssid;
     977             : 
     978         208 :         if (wpa_s->current_ssid)
     979           0 :                 wpa_supplicant_deauthenticate(
     980             :                         wpa_s, WLAN_REASON_DEAUTH_LEAVING);
     981             : 
     982             :         /* Mark all other networks disabled and trigger reassociation */
     983         208 :         ssid = wpa_s->conf->ssid;
     984         620 :         while (ssid) {
     985         204 :                 int was_disabled = ssid->disabled;
     986         204 :                 ssid->disabled_for_connect = 0;
     987             :                 /*
     988             :                  * In case the network object corresponds to a persistent group
     989             :                  * then do not send out network disabled signal. In addition,
     990             :                  * do not change disabled status of persistent network objects
     991             :                  * from 2 to 1 should we connect to another network.
     992             :                  */
     993         204 :                 if (was_disabled != 2) {
     994         203 :                         ssid->disabled = ssid != selected;
     995         203 :                         if (was_disabled != ssid->disabled) {
     996           3 :                                 if (ssid->disabled)
     997           3 :                                         ssid->disabled_for_connect = 1;
     998           3 :                                 wpas_notify_network_enabled_changed(wpa_s,
     999             :                                                                     ssid);
    1000             :                         }
    1001             :                 }
    1002         204 :                 ssid = ssid->next;
    1003             :         }
    1004         208 : }
    1005             : 
    1006             : 
    1007         200 : static void wpas_wps_reassoc(struct wpa_supplicant *wpa_s,
    1008             :                              struct wpa_ssid *selected, const u8 *bssid,
    1009             :                              int freq)
    1010             : {
    1011             :         struct wpa_bss *bss;
    1012             : 
    1013         200 :         wpa_s->after_wps = 0;
    1014         200 :         wpa_s->known_wps_freq = 0;
    1015         200 :         if (freq) {
    1016           8 :                 wpa_s->after_wps = 5;
    1017           8 :                 wpa_s->wps_freq = freq;
    1018         192 :         } else if (bssid) {
    1019         142 :                 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
    1020         142 :                 if (bss && bss->freq > 0) {
    1021          62 :                         wpa_s->known_wps_freq = 1;
    1022          62 :                         wpa_s->wps_freq = bss->freq;
    1023             :                 }
    1024             :         }
    1025             : 
    1026         200 :         wpas_wps_temp_disable(wpa_s, selected);
    1027             : 
    1028         200 :         wpa_s->disconnected = 0;
    1029         200 :         wpa_s->reassociate = 1;
    1030         200 :         wpa_s->scan_runs = 0;
    1031         200 :         wpa_s->normal_scans = 0;
    1032         200 :         wpa_s->wps_success = 0;
    1033         200 :         wpa_s->blacklist_cleared = 0;
    1034             : 
    1035         200 :         wpa_supplicant_cancel_sched_scan(wpa_s);
    1036         200 :         wpa_supplicant_req_scan(wpa_s, 0, 0);
    1037         200 : }
    1038             : 
    1039             : 
    1040          34 : int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
    1041             :                        int p2p_group)
    1042             : {
    1043             :         struct wpa_ssid *ssid;
    1044          34 :         wpas_clear_wps(wpa_s);
    1045          34 :         ssid = wpas_wps_add_network(wpa_s, 0, NULL, bssid);
    1046          34 :         if (ssid == NULL)
    1047           0 :                 return -1;
    1048          34 :         ssid->temporary = 1;
    1049          34 :         ssid->p2p_group = p2p_group;
    1050             : #ifdef CONFIG_P2P
    1051          34 :         if (p2p_group && wpa_s->go_params && wpa_s->go_params->ssid_len) {
    1052          10 :                 ssid->ssid = os_zalloc(wpa_s->go_params->ssid_len + 1);
    1053          10 :                 if (ssid->ssid) {
    1054          10 :                         ssid->ssid_len = wpa_s->go_params->ssid_len;
    1055          10 :                         os_memcpy(ssid->ssid, wpa_s->go_params->ssid,
    1056             :                                   ssid->ssid_len);
    1057          20 :                         wpa_hexdump_ascii(MSG_DEBUG, "WPS: Use specific AP "
    1058          10 :                                           "SSID", ssid->ssid, ssid->ssid_len);
    1059             :                 }
    1060             :         }
    1061             : #endif /* CONFIG_P2P */
    1062          34 :         if (wpa_config_set(ssid, "phase1", "\"pbc=1\"", 0) < 0)
    1063           0 :                 return -1;
    1064          34 :         if (wpa_s->wps_fragment_size)
    1065           1 :                 ssid->eap.fragment_size = wpa_s->wps_fragment_size;
    1066          34 :         eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
    1067             :                                wpa_s, NULL);
    1068          34 :         wpas_wps_reassoc(wpa_s, ssid, bssid, 0);
    1069          34 :         return 0;
    1070             : }
    1071             : 
    1072             : 
    1073         128 : static int wpas_wps_start_dev_pw(struct wpa_supplicant *wpa_s,
    1074             :                                  const u8 *dev_addr, const u8 *bssid,
    1075             :                                  const char *pin, int p2p_group, u16 dev_pw_id,
    1076             :                                  const u8 *peer_pubkey_hash,
    1077             :                                  const u8 *ssid_val, size_t ssid_len, int freq)
    1078             : {
    1079             :         struct wpa_ssid *ssid;
    1080             :         char val[128 + 2 * WPS_OOB_PUBKEY_HASH_LEN];
    1081         128 :         unsigned int rpin = 0;
    1082             :         char hash[2 * WPS_OOB_PUBKEY_HASH_LEN + 10];
    1083             : 
    1084         128 :         wpas_clear_wps(wpa_s);
    1085         128 :         if (bssid && is_zero_ether_addr(bssid))
    1086           4 :                 bssid = NULL;
    1087         128 :         ssid = wpas_wps_add_network(wpa_s, 0, dev_addr, bssid);
    1088         128 :         if (ssid == NULL) {
    1089           0 :                 wpa_printf(MSG_DEBUG, "WPS: Could not add network");
    1090           0 :                 return -1;
    1091             :         }
    1092         128 :         ssid->temporary = 1;
    1093         128 :         ssid->p2p_group = p2p_group;
    1094         128 :         if (ssid_val) {
    1095          11 :                 ssid->ssid = os_malloc(ssid_len);
    1096          11 :                 if (ssid->ssid) {
    1097          11 :                         os_memcpy(ssid->ssid, ssid_val, ssid_len);
    1098          11 :                         ssid->ssid_len = ssid_len;
    1099             :                 }
    1100             :         }
    1101         128 :         if (peer_pubkey_hash) {
    1102          17 :                 os_memcpy(hash, " pkhash=", 8);
    1103          17 :                 wpa_snprintf_hex_uppercase(hash + 8, sizeof(hash) - 8,
    1104             :                                            peer_pubkey_hash,
    1105             :                                            WPS_OOB_PUBKEY_HASH_LEN);
    1106             :         } else {
    1107         111 :                 hash[0] = '\0';
    1108             :         }
    1109             : #ifdef CONFIG_P2P
    1110         128 :         if (p2p_group && wpa_s->go_params && wpa_s->go_params->ssid_len) {
    1111          95 :                 ssid->ssid = os_zalloc(wpa_s->go_params->ssid_len + 1);
    1112          95 :                 if (ssid->ssid) {
    1113          95 :                         ssid->ssid_len = wpa_s->go_params->ssid_len;
    1114          95 :                         os_memcpy(ssid->ssid, wpa_s->go_params->ssid,
    1115             :                                   ssid->ssid_len);
    1116         190 :                         wpa_hexdump_ascii(MSG_DEBUG, "WPS: Use specific AP "
    1117          95 :                                           "SSID", ssid->ssid, ssid->ssid_len);
    1118             :                 }
    1119             :         }
    1120             : #endif /* CONFIG_P2P */
    1121         128 :         if (pin)
    1122         110 :                 os_snprintf(val, sizeof(val), "\"pin=%s dev_pw_id=%u%s\"",
    1123             :                             pin, dev_pw_id, hash);
    1124          18 :         else if (pin == NULL && dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) {
    1125          17 :                 os_snprintf(val, sizeof(val), "\"dev_pw_id=%u%s\"",
    1126             :                             dev_pw_id, hash);
    1127             :         } else {
    1128           1 :                 rpin = wps_generate_pin();
    1129           1 :                 os_snprintf(val, sizeof(val), "\"pin=%08d dev_pw_id=%u%s\"",
    1130             :                             rpin, dev_pw_id, hash);
    1131             :         }
    1132         128 :         if (wpa_config_set(ssid, "phase1", val, 0) < 0) {
    1133           0 :                 wpa_printf(MSG_DEBUG, "WPS: Failed to set phase1 '%s'", val);
    1134           0 :                 return -1;
    1135             :         }
    1136         128 :         if (wpa_s->wps_fragment_size)
    1137           1 :                 ssid->eap.fragment_size = wpa_s->wps_fragment_size;
    1138         128 :         eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
    1139             :                                wpa_s, NULL);
    1140         128 :         wpa_s->wps_ap_iter = 1;
    1141         128 :         wpas_wps_reassoc(wpa_s, ssid, bssid, freq);
    1142         128 :         return rpin;
    1143             : }
    1144             : 
    1145             : 
    1146         100 : int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
    1147             :                        const char *pin, int p2p_group, u16 dev_pw_id)
    1148             : {
    1149         100 :         return wpas_wps_start_dev_pw(wpa_s, NULL, bssid, pin, p2p_group,
    1150             :                                      dev_pw_id, NULL, NULL, 0, 0);
    1151             : }
    1152             : 
    1153             : 
    1154             : /* Cancel the wps pbc/pin requests */
    1155        1913 : int wpas_wps_cancel(struct wpa_supplicant *wpa_s)
    1156             : {
    1157             : #ifdef CONFIG_AP
    1158        1913 :         if (wpa_s->ap_iface) {
    1159           6 :                 wpa_printf(MSG_DEBUG, "WPS: Cancelling in AP mode");
    1160           6 :                 return wpa_supplicant_ap_wps_cancel(wpa_s);
    1161             :         }
    1162             : #endif /* CONFIG_AP */
    1163             : 
    1164        3738 :         if (wpa_s->wpa_state == WPA_SCANNING ||
    1165        1831 :             wpa_s->wpa_state == WPA_DISCONNECTED) {
    1166         878 :                 wpa_printf(MSG_DEBUG, "WPS: Cancel operation - cancel scan");
    1167         878 :                 wpa_supplicant_cancel_scan(wpa_s);
    1168         878 :                 wpas_clear_wps(wpa_s);
    1169        1029 :         } else if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
    1170         415 :                 wpa_printf(MSG_DEBUG, "WPS: Cancel operation - "
    1171             :                            "deauthenticate");
    1172         415 :                 wpa_supplicant_deauthenticate(wpa_s,
    1173             :                                               WLAN_REASON_DEAUTH_LEAVING);
    1174         415 :                 wpas_clear_wps(wpa_s);
    1175             :         } else {
    1176         614 :                 wpas_wps_reenable_networks(wpa_s);
    1177         614 :                 wpas_wps_clear_ap_info(wpa_s);
    1178         614 :                 if (eloop_cancel_timeout(wpas_wps_clear_timeout, wpa_s, NULL) >
    1179             :                     0)
    1180           0 :                         wpas_clear_wps(wpa_s);
    1181             :         }
    1182             : 
    1183        1907 :         wpa_s->after_wps = 0;
    1184             : 
    1185        1907 :         return 0;
    1186             : }
    1187             : 
    1188             : 
    1189          38 : int wpas_wps_start_reg(struct wpa_supplicant *wpa_s, const u8 *bssid,
    1190             :                        const char *pin, struct wps_new_ap_settings *settings)
    1191             : {
    1192             :         struct wpa_ssid *ssid;
    1193             :         char val[200];
    1194             :         char *pos, *end;
    1195             :         int res;
    1196             : 
    1197          38 :         if (!pin)
    1198           0 :                 return -1;
    1199          38 :         wpas_clear_wps(wpa_s);
    1200          38 :         ssid = wpas_wps_add_network(wpa_s, 1, NULL, bssid);
    1201          38 :         if (ssid == NULL)
    1202           0 :                 return -1;
    1203          38 :         ssid->temporary = 1;
    1204          38 :         pos = val;
    1205          38 :         end = pos + sizeof(val);
    1206          38 :         res = os_snprintf(pos, end - pos, "\"pin=%s", pin);
    1207          38 :         if (res < 0 || res >= end - pos)
    1208           0 :                 return -1;
    1209          38 :         pos += res;
    1210          38 :         if (settings) {
    1211          16 :                 res = os_snprintf(pos, end - pos, " new_ssid=%s new_auth=%s "
    1212             :                                   "new_encr=%s new_key=%s",
    1213             :                                   settings->ssid_hex, settings->auth,
    1214             :                                   settings->encr, settings->key_hex);
    1215          16 :                 if (res < 0 || res >= end - pos)
    1216           0 :                         return -1;
    1217          16 :                 pos += res;
    1218             :         }
    1219          38 :         res = os_snprintf(pos, end - pos, "\"");
    1220          38 :         if (res < 0 || res >= end - pos)
    1221           0 :                 return -1;
    1222          38 :         if (wpa_config_set(ssid, "phase1", val, 0) < 0)
    1223           0 :                 return -1;
    1224          38 :         if (wpa_s->wps_fragment_size)
    1225           1 :                 ssid->eap.fragment_size = wpa_s->wps_fragment_size;
    1226          38 :         eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
    1227             :                                wpa_s, NULL);
    1228          38 :         wpas_wps_reassoc(wpa_s, ssid, bssid, 0);
    1229          38 :         return 0;
    1230             : }
    1231             : 
    1232             : 
    1233           0 : static int wpas_wps_new_psk_cb(void *ctx, const u8 *mac_addr,
    1234             :                                const u8 *p2p_dev_addr, const u8 *psk,
    1235             :                                size_t psk_len)
    1236             : {
    1237           0 :         if (is_zero_ether_addr(p2p_dev_addr)) {
    1238           0 :                 wpa_printf(MSG_DEBUG,
    1239             :                            "Received new WPA/WPA2-PSK from WPS for STA " MACSTR,
    1240           0 :                            MAC2STR(mac_addr));
    1241             :         } else {
    1242           0 :                 wpa_printf(MSG_DEBUG,
    1243             :                            "Received new WPA/WPA2-PSK from WPS for STA " MACSTR
    1244             :                            " P2P Device Addr " MACSTR,
    1245           0 :                            MAC2STR(mac_addr), MAC2STR(p2p_dev_addr));
    1246             :         }
    1247           0 :         wpa_hexdump_key(MSG_DEBUG, "Per-device PSK", psk, psk_len);
    1248             : 
    1249             :         /* TODO */
    1250             : 
    1251           0 :         return 0;
    1252             : }
    1253             : 
    1254             : 
    1255           0 : static void wpas_wps_pin_needed_cb(void *ctx, const u8 *uuid_e,
    1256             :                                    const struct wps_device_data *dev)
    1257             : {
    1258             :         char uuid[40], txt[400];
    1259             :         int len;
    1260             :         char devtype[WPS_DEV_TYPE_BUFSIZE];
    1261           0 :         if (uuid_bin2str(uuid_e, uuid, sizeof(uuid)))
    1262           0 :                 return;
    1263           0 :         wpa_printf(MSG_DEBUG, "WPS: PIN needed for UUID-E %s", uuid);
    1264           0 :         len = os_snprintf(txt, sizeof(txt), "WPS-EVENT-PIN-NEEDED %s " MACSTR
    1265             :                           " [%s|%s|%s|%s|%s|%s]",
    1266           0 :                           uuid, MAC2STR(dev->mac_addr), dev->device_name,
    1267             :                           dev->manufacturer, dev->model_name,
    1268             :                           dev->model_number, dev->serial_number,
    1269           0 :                           wps_dev_type_bin2str(dev->pri_dev_type, devtype,
    1270             :                                                sizeof(devtype)));
    1271           0 :         if (len > 0 && len < (int) sizeof(txt))
    1272           0 :                 wpa_printf(MSG_INFO, "%s", txt);
    1273             : }
    1274             : 
    1275             : 
    1276         116 : static void wpas_wps_set_sel_reg_cb(void *ctx, int sel_reg, u16 dev_passwd_id,
    1277             :                                     u16 sel_reg_config_methods)
    1278             : {
    1279             : #ifdef CONFIG_WPS_ER
    1280         116 :         struct wpa_supplicant *wpa_s = ctx;
    1281             : 
    1282         116 :         if (wpa_s->wps_er == NULL)
    1283         204 :                 return;
    1284          28 :         wpa_printf(MSG_DEBUG, "WPS ER: SetSelectedRegistrar - sel_reg=%d "
    1285             :                    "dev_password_id=%u sel_reg_config_methods=0x%x",
    1286             :                    sel_reg, dev_passwd_id, sel_reg_config_methods);
    1287          28 :         wps_er_set_sel_reg(wpa_s->wps_er, sel_reg, dev_passwd_id,
    1288             :                            sel_reg_config_methods);
    1289             : #endif /* CONFIG_WPS_ER */
    1290             : }
    1291             : 
    1292             : 
    1293       17544 : static u16 wps_fix_config_methods(u16 config_methods)
    1294             : {
    1295       17544 :         if ((config_methods &
    1296             :              (WPS_CONFIG_DISPLAY | WPS_CONFIG_VIRT_DISPLAY |
    1297             :               WPS_CONFIG_PHY_DISPLAY)) == WPS_CONFIG_DISPLAY) {
    1298           0 :                 wpa_printf(MSG_INFO, "WPS: Converting display to "
    1299             :                            "virtual_display for WPS 2.0 compliance");
    1300           0 :                 config_methods |= WPS_CONFIG_VIRT_DISPLAY;
    1301             :         }
    1302       17544 :         if ((config_methods &
    1303             :              (WPS_CONFIG_PUSHBUTTON | WPS_CONFIG_VIRT_PUSHBUTTON |
    1304             :               WPS_CONFIG_PHY_PUSHBUTTON)) == WPS_CONFIG_PUSHBUTTON) {
    1305           0 :                 wpa_printf(MSG_INFO, "WPS: Converting push_button to "
    1306             :                            "virtual_push_button for WPS 2.0 compliance");
    1307           0 :                 config_methods |= WPS_CONFIG_VIRT_PUSHBUTTON;
    1308             :         }
    1309             : 
    1310       17544 :         return config_methods;
    1311             : }
    1312             : 
    1313             : 
    1314          70 : static void wpas_wps_set_uuid(struct wpa_supplicant *wpa_s,
    1315             :                               struct wps_context *wps)
    1316             : {
    1317             :         char buf[50];
    1318             :         const char *src;
    1319             : 
    1320          70 :         if (is_nil_uuid(wpa_s->conf->uuid)) {
    1321             :                 struct wpa_supplicant *first;
    1322          69 :                 first = wpa_s->global->ifaces;
    1323         138 :                 while (first && first->next)
    1324           0 :                         first = first->next;
    1325          69 :                 if (first && first != wpa_s) {
    1326          35 :                         if (wps != wpa_s->global->ifaces->wps)
    1327          35 :                                 os_memcpy(wps->uuid,
    1328             :                                           wpa_s->global->ifaces->wps->uuid,
    1329             :                                           WPS_UUID_LEN);
    1330          35 :                         src = "from the first interface";
    1331             :                 } else {
    1332          34 :                         uuid_gen_mac_addr(wpa_s->own_addr, wps->uuid);
    1333          34 :                         src = "based on MAC address";
    1334             :                 }
    1335             :         } else {
    1336           1 :                 os_memcpy(wps->uuid, wpa_s->conf->uuid, WPS_UUID_LEN);
    1337           1 :                 src = "based on configuration";
    1338             :         }
    1339             : 
    1340          70 :         uuid_bin2str(wps->uuid, buf, sizeof(buf));
    1341          70 :         wpa_dbg(wpa_s, MSG_DEBUG, "WPS: UUID %s: %s", src, buf);
    1342          70 : }
    1343             : 
    1344             : 
    1345          70 : static void wpas_wps_set_vendor_ext_m1(struct wpa_supplicant *wpa_s,
    1346             :                                        struct wps_context *wps)
    1347             : {
    1348          70 :         wpabuf_free(wps->dev.vendor_ext_m1);
    1349          70 :         wps->dev.vendor_ext_m1 = NULL;
    1350             : 
    1351          70 :         if (wpa_s->conf->wps_vendor_ext_m1) {
    1352           1 :                 wps->dev.vendor_ext_m1 =
    1353           1 :                         wpabuf_dup(wpa_s->conf->wps_vendor_ext_m1);
    1354           1 :                 if (!wps->dev.vendor_ext_m1) {
    1355           0 :                         wpa_printf(MSG_ERROR, "WPS: Cannot "
    1356             :                                    "allocate memory for vendor_ext_m1");
    1357             :                 }
    1358             :         }
    1359          70 : }
    1360             : 
    1361             : 
    1362          69 : int wpas_wps_init(struct wpa_supplicant *wpa_s)
    1363             : {
    1364             :         struct wps_context *wps;
    1365             :         struct wps_registrar_config rcfg;
    1366             :         struct hostapd_hw_modes *modes;
    1367             :         u16 m;
    1368             : 
    1369          69 :         wps = os_zalloc(sizeof(*wps));
    1370          69 :         if (wps == NULL)
    1371           0 :                 return -1;
    1372             : 
    1373          69 :         wps->cred_cb = wpa_supplicant_wps_cred;
    1374          69 :         wps->event_cb = wpa_supplicant_wps_event;
    1375          69 :         wps->rf_band_cb = wpa_supplicant_wps_rf_band;
    1376          69 :         wps->cb_ctx = wpa_s;
    1377             : 
    1378          69 :         wps->dev.device_name = wpa_s->conf->device_name;
    1379          69 :         wps->dev.manufacturer = wpa_s->conf->manufacturer;
    1380          69 :         wps->dev.model_name = wpa_s->conf->model_name;
    1381          69 :         wps->dev.model_number = wpa_s->conf->model_number;
    1382          69 :         wps->dev.serial_number = wpa_s->conf->serial_number;
    1383          69 :         wps->config_methods =
    1384          69 :                 wps_config_methods_str2bin(wpa_s->conf->config_methods);
    1385          69 :         if ((wps->config_methods & (WPS_CONFIG_DISPLAY | WPS_CONFIG_LABEL)) ==
    1386             :             (WPS_CONFIG_DISPLAY | WPS_CONFIG_LABEL)) {
    1387           0 :                 wpa_printf(MSG_ERROR, "WPS: Both Label and Display config "
    1388             :                            "methods are not allowed at the same time");
    1389           0 :                 os_free(wps);
    1390           0 :                 return -1;
    1391             :         }
    1392          69 :         wps->config_methods = wps_fix_config_methods(wps->config_methods);
    1393          69 :         wps->dev.config_methods = wps->config_methods;
    1394          69 :         os_memcpy(wps->dev.pri_dev_type, wpa_s->conf->device_type,
    1395             :                   WPS_DEV_TYPE_LEN);
    1396             : 
    1397          69 :         wps->dev.num_sec_dev_types = wpa_s->conf->num_sec_device_types;
    1398          69 :         os_memcpy(wps->dev.sec_dev_type, wpa_s->conf->sec_device_type,
    1399             :                   WPS_DEV_TYPE_LEN * wps->dev.num_sec_dev_types);
    1400             : 
    1401          69 :         wpas_wps_set_vendor_ext_m1(wpa_s, wps);
    1402             : 
    1403          69 :         wps->dev.os_version = WPA_GET_BE32(wpa_s->conf->os_version);
    1404          69 :         modes = wpa_s->hw.modes;
    1405          69 :         if (modes) {
    1406         276 :                 for (m = 0; m < wpa_s->hw.num_modes; m++) {
    1407         345 :                         if (modes[m].mode == HOSTAPD_MODE_IEEE80211B ||
    1408         138 :                             modes[m].mode == HOSTAPD_MODE_IEEE80211G)
    1409         138 :                                 wps->dev.rf_bands |= WPS_RF_24GHZ;
    1410          69 :                         else if (modes[m].mode == HOSTAPD_MODE_IEEE80211A)
    1411          69 :                                 wps->dev.rf_bands |= WPS_RF_50GHZ;
    1412             :                 }
    1413             :         }
    1414          69 :         if (wps->dev.rf_bands == 0) {
    1415             :                 /*
    1416             :                  * Default to claiming support for both bands if the driver
    1417             :                  * does not provide support for fetching supported bands.
    1418             :                  */
    1419           0 :                 wps->dev.rf_bands = WPS_RF_24GHZ | WPS_RF_50GHZ;
    1420             :         }
    1421          69 :         os_memcpy(wps->dev.mac_addr, wpa_s->own_addr, ETH_ALEN);
    1422          69 :         wpas_wps_set_uuid(wpa_s, wps);
    1423             : 
    1424          69 :         wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK;
    1425          69 :         wps->encr_types = WPS_ENCR_AES | WPS_ENCR_TKIP;
    1426             : 
    1427          69 :         os_memset(&rcfg, 0, sizeof(rcfg));
    1428          69 :         rcfg.new_psk_cb = wpas_wps_new_psk_cb;
    1429          69 :         rcfg.pin_needed_cb = wpas_wps_pin_needed_cb;
    1430          69 :         rcfg.set_sel_reg_cb = wpas_wps_set_sel_reg_cb;
    1431          69 :         rcfg.cb_ctx = wpa_s;
    1432             : 
    1433          69 :         wps->registrar = wps_registrar_init(wps, &rcfg);
    1434          69 :         if (wps->registrar == NULL) {
    1435           0 :                 wpa_printf(MSG_DEBUG, "Failed to initialize WPS Registrar");
    1436           0 :                 os_free(wps);
    1437           0 :                 return -1;
    1438             :         }
    1439             : 
    1440          69 :         wpa_s->wps = wps;
    1441             : 
    1442          69 :         return 0;
    1443             : }
    1444             : 
    1445             : 
    1446             : #ifdef CONFIG_WPS_ER
    1447          72 : static void wpas_wps_nfc_clear(struct wps_context *wps)
    1448             : {
    1449          72 :         wps->ap_nfc_dev_pw_id = 0;
    1450          72 :         wpabuf_free(wps->ap_nfc_dh_pubkey);
    1451          72 :         wps->ap_nfc_dh_pubkey = NULL;
    1452          72 :         wpabuf_free(wps->ap_nfc_dh_privkey);
    1453          72 :         wps->ap_nfc_dh_privkey = NULL;
    1454          72 :         wpabuf_free(wps->ap_nfc_dev_pw);
    1455          72 :         wps->ap_nfc_dev_pw = NULL;
    1456          72 : }
    1457             : #endif /* CONFIG_WPS_ER */
    1458             : 
    1459             : 
    1460          78 : void wpas_wps_deinit(struct wpa_supplicant *wpa_s)
    1461             : {
    1462          78 :         wpas_wps_assoc_with_cred_cancel(wpa_s);
    1463          78 :         eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL);
    1464          78 :         eloop_cancel_timeout(wpas_wps_clear_timeout, wpa_s, NULL);
    1465          78 :         eloop_cancel_timeout(wpas_wps_reenable_networks_cb, wpa_s, NULL);
    1466          78 :         wpas_wps_clear_ap_info(wpa_s);
    1467             : 
    1468             : #ifdef CONFIG_P2P
    1469          78 :         eloop_cancel_timeout(wpas_p2p_pbc_overlap_cb, wpa_s, NULL);
    1470             : #endif /* CONFIG_P2P */
    1471             : 
    1472          78 :         if (wpa_s->wps == NULL)
    1473          87 :                 return;
    1474             : 
    1475             : #ifdef CONFIG_WPS_ER
    1476          69 :         wps_er_deinit(wpa_s->wps_er, NULL, NULL);
    1477          69 :         wpa_s->wps_er = NULL;
    1478          69 :         wpas_wps_nfc_clear(wpa_s->wps);
    1479             : #endif /* CONFIG_WPS_ER */
    1480             : 
    1481          69 :         wps_registrar_deinit(wpa_s->wps->registrar);
    1482          69 :         wpabuf_free(wpa_s->wps->dh_pubkey);
    1483          69 :         wpabuf_free(wpa_s->wps->dh_privkey);
    1484          69 :         wpabuf_free(wpa_s->wps->dev.vendor_ext_m1);
    1485          69 :         os_free(wpa_s->wps->network_key);
    1486          69 :         os_free(wpa_s->wps);
    1487          69 :         wpa_s->wps = NULL;
    1488             : }
    1489             : 
    1490             : 
    1491        1237 : int wpas_wps_ssid_bss_match(struct wpa_supplicant *wpa_s,
    1492             :                             struct wpa_ssid *ssid, struct wpa_bss *bss)
    1493             : {
    1494             :         struct wpabuf *wps_ie;
    1495             : 
    1496        1237 :         if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS))
    1497        1025 :                 return -1;
    1498             : 
    1499         212 :         wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
    1500         212 :         if (eap_is_wps_pbc_enrollee(&ssid->eap)) {
    1501          33 :                 if (!wps_ie) {
    1502           0 :                         wpa_printf(MSG_DEBUG, "   skip - non-WPS AP");
    1503           0 :                         return 0;
    1504             :                 }
    1505             : 
    1506          33 :                 if (!wps_is_selected_pbc_registrar(wps_ie)) {
    1507           0 :                         wpa_printf(MSG_DEBUG, "   skip - WPS AP "
    1508             :                                    "without active PBC Registrar");
    1509           0 :                         wpabuf_free(wps_ie);
    1510           0 :                         return 0;
    1511             :                 }
    1512             : 
    1513             :                 /* TODO: overlap detection */
    1514          33 :                 wpa_printf(MSG_DEBUG, "   selected based on WPS IE "
    1515             :                            "(Active PBC)");
    1516          33 :                 wpabuf_free(wps_ie);
    1517          33 :                 return 1;
    1518             :         }
    1519             : 
    1520         179 :         if (eap_is_wps_pin_enrollee(&ssid->eap)) {
    1521         124 :                 if (!wps_ie) {
    1522           0 :                         wpa_printf(MSG_DEBUG, "   skip - non-WPS AP");
    1523           0 :                         return 0;
    1524             :                 }
    1525             : 
    1526             :                 /*
    1527             :                  * Start with WPS APs that advertise our address as an
    1528             :                  * authorized MAC (v2.0) or active PIN Registrar (v1.0) and
    1529             :                  * allow any WPS AP after couple of scans since some APs do not
    1530             :                  * set Selected Registrar attribute properly when using
    1531             :                  * external Registrar.
    1532             :                  */
    1533         124 :                 if (!wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1)) {
    1534          19 :                         if (wpa_s->scan_runs < WPS_PIN_SCAN_IGNORE_SEL_REG) {
    1535           9 :                                 wpa_printf(MSG_DEBUG, "   skip - WPS AP "
    1536             :                                            "without active PIN Registrar");
    1537           9 :                                 wpabuf_free(wps_ie);
    1538           9 :                                 return 0;
    1539             :                         }
    1540          10 :                         wpa_printf(MSG_DEBUG, "   selected based on WPS IE");
    1541             :                 } else {
    1542         105 :                         wpa_printf(MSG_DEBUG, "   selected based on WPS IE "
    1543             :                                    "(Authorized MAC or Active PIN)");
    1544             :                 }
    1545         115 :                 wpabuf_free(wps_ie);
    1546         115 :                 return 1;
    1547             :         }
    1548             : 
    1549          55 :         if (wps_ie) {
    1550          55 :                 wpa_printf(MSG_DEBUG, "   selected based on WPS IE");
    1551          55 :                 wpabuf_free(wps_ie);
    1552          55 :                 return 1;
    1553             :         }
    1554             : 
    1555           0 :         return -1;
    1556             : }
    1557             : 
    1558             : 
    1559         144 : int wpas_wps_ssid_wildcard_ok(struct wpa_supplicant *wpa_s,
    1560             :                               struct wpa_ssid *ssid,
    1561             :                               struct wpa_bss *bss)
    1562             : {
    1563         144 :         struct wpabuf *wps_ie = NULL;
    1564         144 :         int ret = 0;
    1565             : 
    1566         144 :         if (eap_is_wps_pbc_enrollee(&ssid->eap)) {
    1567          73 :                 wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
    1568          73 :                 if (wps_ie && wps_is_selected_pbc_registrar(wps_ie)) {
    1569             :                         /* allow wildcard SSID for WPS PBC */
    1570          23 :                         ret = 1;
    1571             :                 }
    1572          71 :         } else if (eap_is_wps_pin_enrollee(&ssid->eap)) {
    1573          31 :                 wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
    1574          62 :                 if (wps_ie &&
    1575          42 :                     (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1) ||
    1576          11 :                      wpa_s->scan_runs >= WPS_PIN_SCAN_IGNORE_SEL_REG)) {
    1577             :                         /* allow wildcard SSID for WPS PIN */
    1578          23 :                         ret = 1;
    1579             :                 }
    1580             :         }
    1581             : 
    1582         184 :         if (!ret && ssid->bssid_set &&
    1583          40 :             os_memcmp(ssid->bssid, bss->bssid, ETH_ALEN) == 0) {
    1584             :                 /* allow wildcard SSID due to hardcoded BSSID match */
    1585          40 :                 ret = 1;
    1586             :         }
    1587             : 
    1588             : #ifdef CONFIG_WPS_STRICT
    1589             :         if (wps_ie) {
    1590             :                 if (wps_validate_beacon_probe_resp(wps_ie, bss->beacon_ie_len >
    1591             :                                                    0, bss->bssid) < 0)
    1592             :                         ret = 0;
    1593             :                 if (bss->beacon_ie_len) {
    1594             :                         struct wpabuf *bcn_wps;
    1595             :                         bcn_wps = wpa_bss_get_vendor_ie_multi_beacon(
    1596             :                                 bss, WPS_IE_VENDOR_TYPE);
    1597             :                         if (bcn_wps == NULL) {
    1598             :                                 wpa_printf(MSG_DEBUG, "WPS: Mandatory WPS IE "
    1599             :                                            "missing from AP Beacon");
    1600             :                                 ret = 0;
    1601             :                         } else {
    1602             :                                 if (wps_validate_beacon(wps_ie) < 0)
    1603             :                                         ret = 0;
    1604             :                                 wpabuf_free(bcn_wps);
    1605             :                         }
    1606             :                 }
    1607             :         }
    1608             : #endif /* CONFIG_WPS_STRICT */
    1609             : 
    1610         144 :         wpabuf_free(wps_ie);
    1611             : 
    1612         144 :         return ret;
    1613             : }
    1614             : 
    1615             : 
    1616        1048 : int wpas_wps_scan_pbc_overlap(struct wpa_supplicant *wpa_s,
    1617             :                               struct wpa_bss *selected, struct wpa_ssid *ssid)
    1618             : {
    1619             :         const u8 *sel_uuid, *uuid;
    1620             :         struct wpabuf *wps_ie;
    1621        1048 :         int ret = 0;
    1622             :         struct wpa_bss *bss;
    1623             : 
    1624        1048 :         if (!eap_is_wps_pbc_enrollee(&ssid->eap))
    1625        1015 :                 return 0;
    1626             : 
    1627         198 :         wpa_printf(MSG_DEBUG, "WPS: Check whether PBC session overlap is "
    1628             :                    "present in scan results; selected BSSID " MACSTR,
    1629         198 :                    MAC2STR(selected->bssid));
    1630             : 
    1631             :         /* Make sure that only one AP is in active PBC mode */
    1632          33 :         wps_ie = wpa_bss_get_vendor_ie_multi(selected, WPS_IE_VENDOR_TYPE);
    1633          33 :         if (wps_ie) {
    1634          33 :                 sel_uuid = wps_get_uuid_e(wps_ie);
    1635          33 :                 wpa_hexdump(MSG_DEBUG, "WPS: UUID of the selected BSS",
    1636             :                             sel_uuid, UUID_LEN);
    1637             :         } else {
    1638           0 :                 wpa_printf(MSG_DEBUG, "WPS: Selected BSS does not include "
    1639             :                            "WPS IE?!");
    1640           0 :                 sel_uuid = NULL;
    1641             :         }
    1642             : 
    1643          68 :         dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
    1644             :                 struct wpabuf *ie;
    1645          38 :                 if (bss == selected)
    1646          31 :                         continue;
    1647           7 :                 ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
    1648           7 :                 if (!ie)
    1649           2 :                         continue;
    1650           5 :                 if (!wps_is_selected_pbc_registrar(ie)) {
    1651           1 :                         wpabuf_free(ie);
    1652           1 :                         continue;
    1653             :                 }
    1654          24 :                 wpa_printf(MSG_DEBUG, "WPS: Another BSS in active PBC mode: "
    1655          24 :                            MACSTR, MAC2STR(bss->bssid));
    1656           4 :                 uuid = wps_get_uuid_e(ie);
    1657           4 :                 wpa_hexdump(MSG_DEBUG, "WPS: UUID of the other BSS",
    1658             :                             uuid, UUID_LEN);
    1659           8 :                 if (sel_uuid == NULL || uuid == NULL ||
    1660           4 :                     os_memcmp(sel_uuid, uuid, UUID_LEN) != 0) {
    1661           3 :                         ret = 1; /* PBC overlap */
    1662          36 :                         wpa_msg(wpa_s, MSG_INFO, "WPS: PBC overlap detected: "
    1663             :                                 MACSTR " and " MACSTR,
    1664          18 :                                 MAC2STR(selected->bssid),
    1665          18 :                                 MAC2STR(bss->bssid));
    1666           3 :                         wpabuf_free(ie);
    1667           3 :                         break;
    1668             :                 }
    1669             : 
    1670             :                 /* TODO: verify that this is reasonable dual-band situation */
    1671             : 
    1672           1 :                 wpabuf_free(ie);
    1673             :         }
    1674             : 
    1675          33 :         wpabuf_free(wps_ie);
    1676             : 
    1677          33 :         return ret;
    1678             : }
    1679             : 
    1680             : 
    1681        1078 : void wpas_wps_notify_scan_results(struct wpa_supplicant *wpa_s)
    1682             : {
    1683             :         struct wpa_bss *bss;
    1684        1078 :         unsigned int pbc = 0, auth = 0, pin = 0, wps = 0;
    1685             : 
    1686        1078 :         if (wpa_s->disconnected || wpa_s->wpa_state >= WPA_ASSOCIATED)
    1687        1130 :                 return;
    1688             : 
    1689        2190 :         dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
    1690             :                 struct wpabuf *ie;
    1691        1164 :                 ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
    1692        1164 :                 if (!ie)
    1693         759 :                         continue;
    1694         405 :                 if (wps_is_selected_pbc_registrar(ie))
    1695          49 :                         pbc++;
    1696         356 :                 else if (wps_is_addr_authorized(ie, wpa_s->own_addr, 0))
    1697         172 :                         auth++;
    1698         184 :                 else if (wps_is_selected_pin_registrar(ie))
    1699           6 :                         pin++;
    1700             :                 else
    1701         178 :                         wps++;
    1702         405 :                 wpabuf_free(ie);
    1703             :         }
    1704             : 
    1705        1026 :         if (pbc)
    1706          42 :                 wpa_msg_ctrl(wpa_s, MSG_INFO, WPS_EVENT_AP_AVAILABLE_PBC);
    1707         984 :         else if (auth)
    1708         145 :                 wpa_msg_ctrl(wpa_s, MSG_INFO, WPS_EVENT_AP_AVAILABLE_AUTH);
    1709         839 :         else if (pin)
    1710           6 :                 wpa_msg_ctrl(wpa_s, MSG_INFO, WPS_EVENT_AP_AVAILABLE_PIN);
    1711         833 :         else if (wps)
    1712         160 :                 wpa_msg_ctrl(wpa_s, MSG_INFO, WPS_EVENT_AP_AVAILABLE);
    1713             : }
    1714             : 
    1715             : 
    1716        2109 : int wpas_wps_searching(struct wpa_supplicant *wpa_s)
    1717             : {
    1718             :         struct wpa_ssid *ssid;
    1719             : 
    1720        2892 :         for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
    1721        1146 :                 if ((ssid->key_mgmt & WPA_KEY_MGMT_WPS) && !ssid->disabled)
    1722         363 :                         return 1;
    1723             :         }
    1724             : 
    1725        1746 :         return 0;
    1726             : }
    1727             : 
    1728             : 
    1729         158 : int wpas_wps_scan_result_text(const u8 *ies, size_t ies_len, char *buf,
    1730             :                               char *end)
    1731             : {
    1732             :         struct wpabuf *wps_ie;
    1733             :         int ret;
    1734             : 
    1735         158 :         wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len, WPS_DEV_OUI_WFA);
    1736         158 :         if (wps_ie == NULL)
    1737         125 :                 return 0;
    1738             : 
    1739          33 :         ret = wps_attr_text(wps_ie, buf, end);
    1740          33 :         wpabuf_free(wps_ie);
    1741          33 :         return ret;
    1742             : }
    1743             : 
    1744             : 
    1745           9 : int wpas_wps_er_start(struct wpa_supplicant *wpa_s, const char *filter)
    1746             : {
    1747             : #ifdef CONFIG_WPS_ER
    1748           9 :         if (wpa_s->wps_er) {
    1749           0 :                 wps_er_refresh(wpa_s->wps_er);
    1750           0 :                 return 0;
    1751             :         }
    1752           9 :         wpa_s->wps_er = wps_er_init(wpa_s->wps, wpa_s->ifname, filter);
    1753           9 :         if (wpa_s->wps_er == NULL)
    1754           0 :                 return -1;
    1755           9 :         return 0;
    1756             : #else /* CONFIG_WPS_ER */
    1757             :         return 0;
    1758             : #endif /* CONFIG_WPS_ER */
    1759             : }
    1760             : 
    1761             : 
    1762        1899 : int wpas_wps_er_stop(struct wpa_supplicant *wpa_s)
    1763             : {
    1764             : #ifdef CONFIG_WPS_ER
    1765        1899 :         wps_er_deinit(wpa_s->wps_er, NULL, NULL);
    1766        1899 :         wpa_s->wps_er = NULL;
    1767             : #endif /* CONFIG_WPS_ER */
    1768        1899 :         return 0;
    1769             : }
    1770             : 
    1771             : 
    1772             : #ifdef CONFIG_WPS_ER
    1773           4 : int wpas_wps_er_add_pin(struct wpa_supplicant *wpa_s, const u8 *addr,
    1774             :                         const char *uuid, const char *pin)
    1775             : {
    1776             :         u8 u[UUID_LEN];
    1777           4 :         const u8 *use_uuid = NULL;
    1778             :         u8 addr_buf[ETH_ALEN];
    1779             : 
    1780           4 :         if (os_strcmp(uuid, "any") == 0) {
    1781           1 :         } else if (uuid_str2bin(uuid, u) == 0) {
    1782           0 :                 use_uuid = u;
    1783           1 :         } else if (hwaddr_aton(uuid, addr_buf) == 0) {
    1784           1 :                 use_uuid = wps_er_get_sta_uuid(wpa_s->wps_er, addr_buf);
    1785           1 :                 if (use_uuid == NULL)
    1786           0 :                         return -1;
    1787             :         } else
    1788           0 :                 return -1;
    1789           4 :         return wps_registrar_add_pin(wpa_s->wps->registrar, addr,
    1790             :                                      use_uuid,
    1791             :                                      (const u8 *) pin, os_strlen(pin), 300);
    1792             : }
    1793             : 
    1794             : 
    1795           1 : int wpas_wps_er_pbc(struct wpa_supplicant *wpa_s, const char *uuid)
    1796             : {
    1797           1 :         u8 u[UUID_LEN], *use_uuid = NULL;
    1798           1 :         u8 addr[ETH_ALEN], *use_addr = NULL;
    1799             : 
    1800           1 :         if (uuid_str2bin(uuid, u) == 0)
    1801           0 :                 use_uuid = u;
    1802           1 :         else if (hwaddr_aton(uuid, addr) == 0)
    1803           1 :                 use_addr = addr;
    1804             :         else
    1805           0 :                 return -1;
    1806           1 :         return wps_er_pbc(wpa_s->wps_er, use_uuid, use_addr);
    1807             : }
    1808             : 
    1809             : 
    1810           1 : int wpas_wps_er_learn(struct wpa_supplicant *wpa_s, const char *uuid,
    1811             :                       const char *pin)
    1812             : {
    1813           1 :         u8 u[UUID_LEN], *use_uuid = NULL;
    1814           1 :         u8 addr[ETH_ALEN], *use_addr = NULL;
    1815             : 
    1816           1 :         if (uuid_str2bin(uuid, u) == 0)
    1817           1 :                 use_uuid = u;
    1818           0 :         else if (hwaddr_aton(uuid, addr) == 0)
    1819           0 :                 use_addr = addr;
    1820             :         else
    1821           0 :                 return -1;
    1822             : 
    1823           1 :         return wps_er_learn(wpa_s->wps_er, use_uuid, use_addr, (const u8 *) pin,
    1824             :                             os_strlen(pin));
    1825             : }
    1826             : 
    1827             : 
    1828           8 : static int wpas_wps_network_to_cred(struct wpa_ssid *ssid,
    1829             :                                     struct wps_credential *cred)
    1830             : {
    1831           8 :         os_memset(cred, 0, sizeof(*cred));
    1832           8 :         if (ssid->ssid_len > 32)
    1833           0 :                 return -1;
    1834           8 :         os_memcpy(cred->ssid, ssid->ssid, ssid->ssid_len);
    1835           8 :         cred->ssid_len = ssid->ssid_len;
    1836           8 :         if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
    1837           8 :                 cred->auth_type = (ssid->proto & WPA_PROTO_RSN) ?
    1838             :                         WPS_AUTH_WPA2PSK : WPS_AUTH_WPAPSK;
    1839           8 :                 if (ssid->pairwise_cipher & WPA_CIPHER_CCMP)
    1840           8 :                         cred->encr_type = WPS_ENCR_AES;
    1841             :                 else
    1842           0 :                         cred->encr_type = WPS_ENCR_TKIP;
    1843           8 :                 if (ssid->passphrase) {
    1844           8 :                         cred->key_len = os_strlen(ssid->passphrase);
    1845           8 :                         if (cred->key_len >= 64)
    1846           0 :                                 return -1;
    1847           8 :                         os_memcpy(cred->key, ssid->passphrase, cred->key_len);
    1848           0 :                 } else if (ssid->psk_set) {
    1849           0 :                         cred->key_len = 32;
    1850           0 :                         os_memcpy(cred->key, ssid->psk, 32);
    1851             :                 } else
    1852           0 :                         return -1;
    1853             :         } else {
    1854           0 :                 cred->auth_type = WPS_AUTH_OPEN;
    1855           0 :                 cred->encr_type = WPS_ENCR_NONE;
    1856             :         }
    1857             : 
    1858           8 :         return 0;
    1859             : }
    1860             : 
    1861             : 
    1862           8 : int wpas_wps_er_set_config(struct wpa_supplicant *wpa_s, const char *uuid,
    1863             :                            int id)
    1864             : {
    1865           8 :         u8 u[UUID_LEN], *use_uuid = NULL;
    1866           8 :         u8 addr[ETH_ALEN], *use_addr = NULL;
    1867             :         struct wpa_ssid *ssid;
    1868             :         struct wps_credential cred;
    1869             : 
    1870           8 :         if (uuid_str2bin(uuid, u) == 0)
    1871           7 :                 use_uuid = u;
    1872           1 :         else if (hwaddr_aton(uuid, addr) == 0)
    1873           1 :                 use_addr = addr;
    1874             :         else
    1875           0 :                 return -1;
    1876           8 :         ssid = wpa_config_get_network(wpa_s->conf, id);
    1877           8 :         if (ssid == NULL || ssid->ssid == NULL)
    1878           0 :                 return -1;
    1879             : 
    1880           8 :         if (wpas_wps_network_to_cred(ssid, &cred) < 0)
    1881           0 :                 return -1;
    1882           8 :         return wps_er_set_config(wpa_s->wps_er, use_uuid, use_addr, &cred);
    1883             : }
    1884             : 
    1885             : 
    1886           1 : int wpas_wps_er_config(struct wpa_supplicant *wpa_s, const char *uuid,
    1887             :                        const char *pin, struct wps_new_ap_settings *settings)
    1888             : {
    1889           1 :         u8 u[UUID_LEN], *use_uuid = NULL;
    1890           1 :         u8 addr[ETH_ALEN], *use_addr = NULL;
    1891             :         struct wps_credential cred;
    1892             :         size_t len;
    1893             : 
    1894           1 :         if (uuid_str2bin(uuid, u) == 0)
    1895           0 :                 use_uuid = u;
    1896           1 :         else if (hwaddr_aton(uuid, addr) == 0)
    1897           1 :                 use_addr = addr;
    1898             :         else
    1899           0 :                 return -1;
    1900           2 :         if (settings->ssid_hex == NULL || settings->auth == NULL ||
    1901           2 :             settings->encr == NULL || settings->key_hex == NULL)
    1902           0 :                 return -1;
    1903             : 
    1904           1 :         os_memset(&cred, 0, sizeof(cred));
    1905           1 :         len = os_strlen(settings->ssid_hex);
    1906           2 :         if ((len & 1) || len > 2 * sizeof(cred.ssid) ||
    1907           1 :             hexstr2bin(settings->ssid_hex, cred.ssid, len / 2))
    1908           0 :                 return -1;
    1909           1 :         cred.ssid_len = len / 2;
    1910             : 
    1911           1 :         len = os_strlen(settings->key_hex);
    1912           2 :         if ((len & 1) || len > 2 * sizeof(cred.key) ||
    1913           1 :             hexstr2bin(settings->key_hex, cred.key, len / 2))
    1914           0 :                 return -1;
    1915           1 :         cred.key_len = len / 2;
    1916             : 
    1917           1 :         if (os_strcmp(settings->auth, "OPEN") == 0)
    1918           0 :                 cred.auth_type = WPS_AUTH_OPEN;
    1919           1 :         else if (os_strcmp(settings->auth, "WPAPSK") == 0)
    1920           0 :                 cred.auth_type = WPS_AUTH_WPAPSK;
    1921           1 :         else if (os_strcmp(settings->auth, "WPA2PSK") == 0)
    1922           1 :                 cred.auth_type = WPS_AUTH_WPA2PSK;
    1923             :         else
    1924           0 :                 return -1;
    1925             : 
    1926           1 :         if (os_strcmp(settings->encr, "NONE") == 0)
    1927           0 :                 cred.encr_type = WPS_ENCR_NONE;
    1928             : #ifdef CONFIG_TESTING_OPTIONS
    1929           1 :         else if (os_strcmp(settings->encr, "WEP") == 0)
    1930           0 :                 cred.encr_type = WPS_ENCR_WEP;
    1931             : #endif /* CONFIG_TESTING_OPTIONS */
    1932           1 :         else if (os_strcmp(settings->encr, "TKIP") == 0)
    1933           0 :                 cred.encr_type = WPS_ENCR_TKIP;
    1934           1 :         else if (os_strcmp(settings->encr, "CCMP") == 0)
    1935           1 :                 cred.encr_type = WPS_ENCR_AES;
    1936             :         else
    1937           0 :                 return -1;
    1938             : 
    1939           1 :         return wps_er_config(wpa_s->wps_er, use_uuid, use_addr,
    1940             :                              (const u8 *) pin, os_strlen(pin), &cred);
    1941             : }
    1942             : 
    1943             : 
    1944             : #ifdef CONFIG_WPS_NFC
    1945           2 : struct wpabuf * wpas_wps_er_nfc_config_token(struct wpa_supplicant *wpa_s,
    1946             :                                              int ndef, const char *uuid)
    1947             : {
    1948             :         struct wpabuf *ret;
    1949           2 :         u8 u[UUID_LEN], *use_uuid = NULL;
    1950           2 :         u8 addr[ETH_ALEN], *use_addr = NULL;
    1951             : 
    1952           2 :         if (!wpa_s->wps_er)
    1953           1 :                 return NULL;
    1954             : 
    1955           1 :         if (uuid_str2bin(uuid, u) == 0)
    1956           0 :                 use_uuid = u;
    1957           1 :         else if (hwaddr_aton(uuid, addr) == 0)
    1958           1 :                 use_addr = addr;
    1959             :         else
    1960           0 :                 return NULL;
    1961             : 
    1962           1 :         ret = wps_er_nfc_config_token(wpa_s->wps_er, use_uuid, use_addr);
    1963           1 :         if (ndef && ret) {
    1964             :                 struct wpabuf *tmp;
    1965           1 :                 tmp = ndef_build_wifi(ret);
    1966           1 :                 wpabuf_free(ret);
    1967           1 :                 if (tmp == NULL)
    1968           0 :                         return NULL;
    1969           1 :                 ret = tmp;
    1970             :         }
    1971             : 
    1972           1 :         return ret;
    1973             : }
    1974             : #endif /* CONFIG_WPS_NFC */
    1975             : 
    1976             : 
    1977             : static int callbacks_pending = 0;
    1978             : 
    1979           0 : static void wpas_wps_terminate_cb(void *ctx)
    1980             : {
    1981           0 :         wpa_printf(MSG_DEBUG, "WPS ER: Terminated");
    1982           0 :         if (--callbacks_pending <= 0)
    1983           0 :                 eloop_terminate();
    1984           0 : }
    1985             : #endif /* CONFIG_WPS_ER */
    1986             : 
    1987             : 
    1988           3 : int wpas_wps_terminate_pending(struct wpa_supplicant *wpa_s)
    1989             : {
    1990             : #ifdef CONFIG_WPS_ER
    1991           3 :         if (wpa_s->wps_er) {
    1992           0 :                 callbacks_pending++;
    1993           0 :                 wps_er_deinit(wpa_s->wps_er, wpas_wps_terminate_cb, wpa_s);
    1994           0 :                 wpa_s->wps_er = NULL;
    1995           0 :                 return 1;
    1996             :         }
    1997             : #endif /* CONFIG_WPS_ER */
    1998           3 :         return 0;
    1999             : }
    2000             : 
    2001             : 
    2002       17475 : void wpas_wps_update_config(struct wpa_supplicant *wpa_s)
    2003             : {
    2004       17475 :         struct wps_context *wps = wpa_s->wps;
    2005             : 
    2006       17475 :         if (wps == NULL)
    2007       17475 :                 return;
    2008             : 
    2009       17475 :         if (wpa_s->conf->changed_parameters & CFG_CHANGED_CONFIG_METHODS) {
    2010           1 :                 wps->config_methods = wps_config_methods_str2bin(
    2011           1 :                         wpa_s->conf->config_methods);
    2012           1 :                 if ((wps->config_methods &
    2013             :                      (WPS_CONFIG_DISPLAY | WPS_CONFIG_LABEL)) ==
    2014             :                     (WPS_CONFIG_DISPLAY | WPS_CONFIG_LABEL)) {
    2015           1 :                         wpa_printf(MSG_ERROR, "WPS: Both Label and Display "
    2016             :                                    "config methods are not allowed at the "
    2017             :                                    "same time");
    2018           1 :                         wps->config_methods &= ~WPS_CONFIG_LABEL;
    2019             :                 }
    2020             :         }
    2021       17475 :         wps->config_methods = wps_fix_config_methods(wps->config_methods);
    2022       17475 :         wps->dev.config_methods = wps->config_methods;
    2023             : 
    2024       17475 :         if (wpa_s->conf->changed_parameters & CFG_CHANGED_DEVICE_TYPE)
    2025           1 :                 os_memcpy(wps->dev.pri_dev_type, wpa_s->conf->device_type,
    2026             :                           WPS_DEV_TYPE_LEN);
    2027             : 
    2028       17475 :         if (wpa_s->conf->changed_parameters & CFG_CHANGED_SEC_DEVICE_TYPE) {
    2029           2 :                 wps->dev.num_sec_dev_types = wpa_s->conf->num_sec_device_types;
    2030           2 :                 os_memcpy(wps->dev.sec_dev_type, wpa_s->conf->sec_device_type,
    2031             :                           wps->dev.num_sec_dev_types * WPS_DEV_TYPE_LEN);
    2032             :         }
    2033             : 
    2034       17475 :         if (wpa_s->conf->changed_parameters & CFG_CHANGED_VENDOR_EXTENSION)
    2035           1 :                 wpas_wps_set_vendor_ext_m1(wpa_s, wps);
    2036             : 
    2037       17475 :         if (wpa_s->conf->changed_parameters & CFG_CHANGED_OS_VERSION)
    2038           1 :                 wps->dev.os_version = WPA_GET_BE32(wpa_s->conf->os_version);
    2039             : 
    2040       17475 :         if (wpa_s->conf->changed_parameters & CFG_CHANGED_UUID)
    2041           1 :                 wpas_wps_set_uuid(wpa_s, wps);
    2042             : 
    2043       17475 :         if (wpa_s->conf->changed_parameters &
    2044             :             (CFG_CHANGED_DEVICE_NAME | CFG_CHANGED_WPS_STRING)) {
    2045             :                 /* Update pointers to make sure they refer current values */
    2046           4 :                 wps->dev.device_name = wpa_s->conf->device_name;
    2047           4 :                 wps->dev.manufacturer = wpa_s->conf->manufacturer;
    2048           4 :                 wps->dev.model_name = wpa_s->conf->model_name;
    2049           4 :                 wps->dev.model_number = wpa_s->conf->model_number;
    2050           4 :                 wps->dev.serial_number = wpa_s->conf->serial_number;
    2051             :         }
    2052             : }
    2053             : 
    2054             : 
    2055             : #ifdef CONFIG_WPS_NFC
    2056             : 
    2057             : #ifdef CONFIG_WPS_ER
    2058             : static struct wpabuf *
    2059           0 : wpas_wps_network_config_token(struct wpa_supplicant *wpa_s, int ndef,
    2060             :                               struct wpa_ssid *ssid)
    2061             : {
    2062             :         struct wpabuf *ret;
    2063             :         struct wps_credential cred;
    2064             : 
    2065           0 :         if (wpas_wps_network_to_cred(ssid, &cred) < 0)
    2066           0 :                 return NULL;
    2067             : 
    2068           0 :         ret = wps_er_config_token_from_cred(wpa_s->wps, &cred);
    2069             : 
    2070           0 :         if (ndef && ret) {
    2071             :                 struct wpabuf *tmp;
    2072           0 :                 tmp = ndef_build_wifi(ret);
    2073           0 :                 wpabuf_free(ret);
    2074           0 :                 if (tmp == NULL)
    2075           0 :                         return NULL;
    2076           0 :                 ret = tmp;
    2077             :         }
    2078             : 
    2079           0 :         return ret;
    2080             : }
    2081             : #endif /* CONFIG_WPS_ER */
    2082             : 
    2083             : 
    2084           1 : struct wpabuf * wpas_wps_nfc_config_token(struct wpa_supplicant *wpa_s,
    2085             :                                           int ndef, const char *id_str)
    2086             : {
    2087             : #ifdef CONFIG_WPS_ER
    2088           1 :         if (id_str) {
    2089             :                 int id;
    2090           0 :                 char *end = NULL;
    2091             :                 struct wpa_ssid *ssid;
    2092             : 
    2093           0 :                 id = strtol(id_str, &end, 10);
    2094           0 :                 if (end && *end)
    2095           0 :                         return NULL;
    2096             : 
    2097           0 :                 ssid = wpa_config_get_network(wpa_s->conf, id);
    2098           0 :                 if (ssid == NULL)
    2099           0 :                         return NULL;
    2100           0 :                 return wpas_wps_network_config_token(wpa_s, ndef, ssid);
    2101             :         }
    2102             : #endif /* CONFIG_WPS_ER */
    2103             : #ifdef CONFIG_AP
    2104           1 :         if (wpa_s->ap_iface)
    2105           1 :                 return wpas_ap_wps_nfc_config_token(wpa_s, ndef);
    2106             : #endif /* CONFIG_AP */
    2107           0 :         return NULL;
    2108             : }
    2109             : 
    2110             : 
    2111          11 : struct wpabuf * wpas_wps_nfc_token(struct wpa_supplicant *wpa_s, int ndef)
    2112             : {
    2113          11 :         if (wpa_s->conf->wps_nfc_pw_from_config) {
    2114           0 :                 return wps_nfc_token_build(ndef,
    2115           0 :                                            wpa_s->conf->wps_nfc_dev_pw_id,
    2116           0 :                                            wpa_s->conf->wps_nfc_dh_pubkey,
    2117           0 :                                            wpa_s->conf->wps_nfc_dev_pw);
    2118             :         }
    2119             : 
    2120          33 :         return wps_nfc_token_gen(ndef, &wpa_s->conf->wps_nfc_dev_pw_id,
    2121          11 :                                  &wpa_s->conf->wps_nfc_dh_pubkey,
    2122          11 :                                  &wpa_s->conf->wps_nfc_dh_privkey,
    2123          11 :                                  &wpa_s->conf->wps_nfc_dev_pw);
    2124             : }
    2125             : 
    2126             : 
    2127          28 : int wpas_wps_start_nfc(struct wpa_supplicant *wpa_s, const u8 *go_dev_addr,
    2128             :                        const u8 *bssid,
    2129             :                        const struct wpabuf *dev_pw, u16 dev_pw_id,
    2130             :                        int p2p_group, const u8 *peer_pubkey_hash,
    2131             :                        const u8 *ssid, size_t ssid_len, int freq)
    2132             : {
    2133          28 :         struct wps_context *wps = wpa_s->wps;
    2134             :         char pw[32 * 2 + 1];
    2135             : 
    2136          28 :         if (dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER && dev_pw == NULL) {
    2137           3 :                 dev_pw = wpa_s->conf->wps_nfc_dev_pw;
    2138           3 :                 dev_pw_id = wpa_s->conf->wps_nfc_dev_pw_id;
    2139             :         }
    2140             : 
    2141          56 :         if (wpa_s->conf->wps_nfc_dh_pubkey == NULL ||
    2142          28 :             wpa_s->conf->wps_nfc_dh_privkey == NULL) {
    2143           0 :                 wpa_printf(MSG_DEBUG, "WPS: Missing DH params - "
    2144             :                            "cannot start NFC-triggered connection");
    2145           0 :                 return -1;
    2146             :         }
    2147             : 
    2148          28 :         if (dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER && dev_pw == NULL) {
    2149           0 :                 wpa_printf(MSG_DEBUG, "WPS: Missing Device Password (id=%u) - "
    2150             :                            "cannot start NFC-triggered connection", dev_pw_id);
    2151           0 :                 return -1;
    2152             :         }
    2153             : 
    2154          28 :         dh5_free(wps->dh_ctx);
    2155          28 :         wpabuf_free(wps->dh_pubkey);
    2156          28 :         wpabuf_free(wps->dh_privkey);
    2157          28 :         wps->dh_privkey = wpabuf_dup(wpa_s->conf->wps_nfc_dh_privkey);
    2158          28 :         wps->dh_pubkey = wpabuf_dup(wpa_s->conf->wps_nfc_dh_pubkey);
    2159          28 :         if (wps->dh_privkey == NULL || wps->dh_pubkey == NULL) {
    2160           0 :                 wps->dh_ctx = NULL;
    2161           0 :                 wpabuf_free(wps->dh_pubkey);
    2162           0 :                 wps->dh_pubkey = NULL;
    2163           0 :                 wpabuf_free(wps->dh_privkey);
    2164           0 :                 wps->dh_privkey = NULL;
    2165           0 :                 wpa_printf(MSG_DEBUG, "WPS: Failed to get DH priv/pub key");
    2166           0 :                 return -1;
    2167             :         }
    2168          28 :         wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, wps->dh_pubkey);
    2169          28 :         if (wps->dh_ctx == NULL) {
    2170           0 :                 wpabuf_free(wps->dh_pubkey);
    2171           0 :                 wps->dh_pubkey = NULL;
    2172           0 :                 wpabuf_free(wps->dh_privkey);
    2173           0 :                 wps->dh_privkey = NULL;
    2174           0 :                 wpa_printf(MSG_DEBUG, "WPS: Failed to initialize DH context");
    2175           0 :                 return -1;
    2176             :         }
    2177             : 
    2178          28 :         if (dev_pw) {
    2179          22 :                 wpa_snprintf_hex_uppercase(pw, sizeof(pw),
    2180          11 :                                            wpabuf_head(dev_pw),
    2181             :                                            wpabuf_len(dev_pw));
    2182             :         }
    2183          28 :         return wpas_wps_start_dev_pw(wpa_s, go_dev_addr, bssid,
    2184             :                                      dev_pw ? pw : NULL,
    2185             :                                      p2p_group, dev_pw_id, peer_pubkey_hash,
    2186             :                                      ssid, ssid_len, freq);
    2187             : }
    2188             : 
    2189             : 
    2190           8 : static int wpas_wps_use_cred(struct wpa_supplicant *wpa_s,
    2191             :                              struct wps_parse_attr *attr)
    2192             : {
    2193             :         /*
    2194             :          * Disable existing networks temporarily to allow the newly learned
    2195             :          * credential to be preferred. Enable the temporarily disabled networks
    2196             :          * after 10 seconds.
    2197             :          */
    2198           8 :         wpas_wps_temp_disable(wpa_s, NULL);
    2199           8 :         eloop_register_timeout(10, 0, wpas_wps_reenable_networks_cb, wpa_s,
    2200             :                                NULL);
    2201             : 
    2202           8 :         if (wps_oob_use_cred(wpa_s->wps, attr) < 0)
    2203           4 :                 return -1;
    2204             : 
    2205           4 :         if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
    2206           0 :                 return 0;
    2207             : 
    2208           4 :         if (attr->ap_channel) {
    2209           3 :                 u16 chan = WPA_GET_BE16(attr->ap_channel);
    2210           3 :                 int freq = 0;
    2211             : 
    2212           3 :                 if (chan >= 1 && chan <= 13)
    2213           3 :                         freq = 2407 + 5 * chan;
    2214           0 :                 else if (chan == 14)
    2215           0 :                         freq = 2484;
    2216           0 :                 else if (chan >= 30)
    2217           0 :                         freq = 5000 + 5 * chan;
    2218             : 
    2219           3 :                 if (freq) {
    2220           3 :                         wpa_printf(MSG_DEBUG, "WPS: Credential container indicated AP channel %u -> %u MHz",
    2221             :                                    chan, freq);
    2222           3 :                         wpa_s->after_wps = 5;
    2223           3 :                         wpa_s->wps_freq = freq;
    2224             :                 }
    2225             :         }
    2226             : 
    2227           4 :         wpa_printf(MSG_DEBUG, "WPS: Request reconnection with new network "
    2228             :                    "based on the received credential added");
    2229           4 :         wpa_s->normal_scans = 0;
    2230           4 :         wpa_supplicant_reinit_autoscan(wpa_s);
    2231           4 :         wpa_s->disconnected = 0;
    2232           4 :         wpa_s->reassociate = 1;
    2233             : 
    2234           4 :         wpa_supplicant_cancel_sched_scan(wpa_s);
    2235           4 :         wpa_supplicant_req_scan(wpa_s, 0, 0);
    2236             : 
    2237           4 :         return 0;
    2238             : }
    2239             : 
    2240             : 
    2241             : #ifdef CONFIG_WPS_ER
    2242           2 : static int wpas_wps_add_nfc_password_token(struct wpa_supplicant *wpa_s,
    2243             :                                            struct wps_parse_attr *attr)
    2244             : {
    2245           4 :         return wps_registrar_add_nfc_password_token(
    2246           2 :                 wpa_s->wps->registrar, attr->oob_dev_password,
    2247             :                 attr->oob_dev_password_len);
    2248             : }
    2249             : #endif /* CONFIG_WPS_ER */
    2250             : 
    2251             : 
    2252          12 : static int wpas_wps_nfc_tag_process(struct wpa_supplicant *wpa_s,
    2253             :                                     const struct wpabuf *wps)
    2254             : {
    2255             :         struct wps_parse_attr attr;
    2256             : 
    2257          12 :         wpa_hexdump_buf(MSG_DEBUG, "WPS: Received NFC tag payload", wps);
    2258             : 
    2259          12 :         if (wps_parse_msg(wps, &attr)) {
    2260           1 :                 wpa_printf(MSG_DEBUG, "WPS: Ignore invalid data from NFC tag");
    2261           1 :                 return -1;
    2262             :         }
    2263             : 
    2264          11 :         if (attr.num_cred)
    2265           8 :                 return wpas_wps_use_cred(wpa_s, &attr);
    2266             : 
    2267             : #ifdef CONFIG_WPS_ER
    2268           3 :         if (attr.oob_dev_password)
    2269           2 :                 return wpas_wps_add_nfc_password_token(wpa_s, &attr);
    2270             : #endif /* CONFIG_WPS_ER */
    2271             : 
    2272           1 :         wpa_printf(MSG_DEBUG, "WPS: Ignore unrecognized NFC tag");
    2273           1 :         return -1;
    2274             : }
    2275             : 
    2276             : 
    2277          23 : int wpas_wps_nfc_tag_read(struct wpa_supplicant *wpa_s,
    2278             :                           const struct wpabuf *data, int forced_freq)
    2279             : {
    2280          23 :         const struct wpabuf *wps = data;
    2281          23 :         struct wpabuf *tmp = NULL;
    2282             :         int ret;
    2283             : 
    2284          23 :         if (wpabuf_len(data) < 4)
    2285           2 :                 return -1;
    2286             : 
    2287          21 :         if (*wpabuf_head_u8(data) != 0x10) {
    2288             :                 /* Assume this contains full NDEF record */
    2289          15 :                 tmp = ndef_parse_wifi(data);
    2290          15 :                 if (tmp == NULL) {
    2291             : #ifdef CONFIG_P2P
    2292           9 :                         tmp = ndef_parse_p2p(data);
    2293           9 :                         if (tmp) {
    2294           8 :                                 ret = wpas_p2p_nfc_tag_process(wpa_s, tmp,
    2295             :                                                                forced_freq);
    2296           8 :                                 wpabuf_free(tmp);
    2297           8 :                                 return ret;
    2298             :                         }
    2299             : #endif /* CONFIG_P2P */
    2300           1 :                         wpa_printf(MSG_DEBUG, "WPS: Could not parse NDEF");
    2301           1 :                         return -1;
    2302             :                 }
    2303           6 :                 wps = tmp;
    2304             :         }
    2305             : 
    2306          12 :         ret = wpas_wps_nfc_tag_process(wpa_s, wps);
    2307          12 :         wpabuf_free(tmp);
    2308          12 :         return ret;
    2309             : }
    2310             : 
    2311             : 
    2312          12 : struct wpabuf * wpas_wps_nfc_handover_req(struct wpa_supplicant *wpa_s,
    2313             :                                           int ndef)
    2314             : {
    2315             :         struct wpabuf *ret;
    2316             : 
    2317          12 :         if (wpa_s->conf->wps_nfc_dh_pubkey == NULL &&
    2318           0 :             wps_nfc_gen_dh(&wpa_s->conf->wps_nfc_dh_pubkey,
    2319           0 :                            &wpa_s->conf->wps_nfc_dh_privkey) < 0)
    2320           0 :                 return NULL;
    2321             : 
    2322          12 :         ret = wps_build_nfc_handover_req(wpa_s->wps,
    2323          12 :                                          wpa_s->conf->wps_nfc_dh_pubkey);
    2324             : 
    2325          12 :         if (ndef && ret) {
    2326             :                 struct wpabuf *tmp;
    2327          12 :                 tmp = ndef_build_wifi(ret);
    2328          12 :                 wpabuf_free(ret);
    2329          12 :                 if (tmp == NULL)
    2330           0 :                         return NULL;
    2331          12 :                 ret = tmp;
    2332             :         }
    2333             : 
    2334          12 :         return ret;
    2335             : }
    2336             : 
    2337             : 
    2338             : #ifdef CONFIG_WPS_NFC
    2339             : 
    2340             : static struct wpabuf *
    2341           3 : wpas_wps_er_nfc_handover_sel(struct wpa_supplicant *wpa_s, int ndef,
    2342             :                              const char *uuid)
    2343             : {
    2344             : #ifdef CONFIG_WPS_ER
    2345             :         struct wpabuf *ret;
    2346           3 :         u8 u[UUID_LEN], *use_uuid = NULL;
    2347           3 :         u8 addr[ETH_ALEN], *use_addr = NULL;
    2348           3 :         struct wps_context *wps = wpa_s->wps;
    2349             : 
    2350           3 :         if (wps == NULL)
    2351           0 :                 return NULL;
    2352             : 
    2353           3 :         if (uuid == NULL)
    2354           0 :                 return NULL;
    2355           3 :         if (uuid_str2bin(uuid, u) == 0)
    2356           0 :                 use_uuid = u;
    2357           3 :         else if (hwaddr_aton(uuid, addr) == 0)
    2358           3 :                 use_addr = addr;
    2359             :         else
    2360           0 :                 return NULL;
    2361             : 
    2362           3 :         if (wpa_s->conf->wps_nfc_dh_pubkey == NULL) {
    2363           0 :                 if (wps_nfc_gen_dh(&wpa_s->conf->wps_nfc_dh_pubkey,
    2364           0 :                                    &wpa_s->conf->wps_nfc_dh_privkey) < 0)
    2365           0 :                         return NULL;
    2366             :         }
    2367             : 
    2368           3 :         wpas_wps_nfc_clear(wps);
    2369           3 :         wps->ap_nfc_dev_pw_id = DEV_PW_NFC_CONNECTION_HANDOVER;
    2370           3 :         wps->ap_nfc_dh_pubkey = wpabuf_dup(wpa_s->conf->wps_nfc_dh_pubkey);
    2371           3 :         wps->ap_nfc_dh_privkey = wpabuf_dup(wpa_s->conf->wps_nfc_dh_privkey);
    2372           3 :         if (!wps->ap_nfc_dh_pubkey || !wps->ap_nfc_dh_privkey) {
    2373           0 :                 wpas_wps_nfc_clear(wps);
    2374           0 :                 return NULL;
    2375             :         }
    2376             : 
    2377           3 :         ret = wps_er_nfc_handover_sel(wpa_s->wps_er, wpa_s->wps, use_uuid,
    2378           3 :                                       use_addr, wpa_s->conf->wps_nfc_dh_pubkey);
    2379           3 :         if (ndef && ret) {
    2380             :                 struct wpabuf *tmp;
    2381           3 :                 tmp = ndef_build_wifi(ret);
    2382           3 :                 wpabuf_free(ret);
    2383           3 :                 if (tmp == NULL)
    2384           0 :                         return NULL;
    2385           3 :                 ret = tmp;
    2386             :         }
    2387             : 
    2388           3 :         return ret;
    2389             : #else /* CONFIG_WPS_ER */
    2390             :         return NULL;
    2391             : #endif /* CONFIG_WPS_ER */
    2392             : }
    2393             : #endif /* CONFIG_WPS_NFC */
    2394             : 
    2395             : 
    2396           6 : struct wpabuf * wpas_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s,
    2397             :                                           int ndef, int cr, const char *uuid)
    2398             : {
    2399             :         struct wpabuf *ret;
    2400           6 :         if (!cr)
    2401           2 :                 return NULL;
    2402           4 :         ret = wpas_ap_wps_nfc_handover_sel(wpa_s, ndef);
    2403           4 :         if (ret)
    2404           1 :                 return ret;
    2405           3 :         return wpas_wps_er_nfc_handover_sel(wpa_s, ndef, uuid);
    2406             : }
    2407             : 
    2408             : 
    2409          11 : static int wpas_wps_nfc_rx_handover_sel(struct wpa_supplicant *wpa_s,
    2410             :                                         const struct wpabuf *data)
    2411             : {
    2412             :         struct wpabuf *wps;
    2413          11 :         int ret = -1;
    2414             :         u16 wsc_len;
    2415             :         const u8 *pos;
    2416             :         struct wpabuf msg;
    2417             :         struct wps_parse_attr attr;
    2418             :         u16 dev_pw_id;
    2419          11 :         const u8 *bssid = NULL;
    2420          11 :         int freq = 0;
    2421             : 
    2422          11 :         wps = ndef_parse_wifi(data);
    2423          11 :         if (wps == NULL)
    2424           0 :                 return -1;
    2425          11 :         wpa_printf(MSG_DEBUG, "WPS: Received application/vnd.wfa.wsc "
    2426             :                    "payload from NFC connection handover");
    2427          11 :         wpa_hexdump_buf(MSG_DEBUG, "WPS: NFC payload", wps);
    2428          11 :         if (wpabuf_len(wps) < 2) {
    2429           0 :                 wpa_printf(MSG_DEBUG, "WPS: Too short Wi-Fi Handover Select "
    2430             :                            "Message");
    2431           0 :                 goto out;
    2432             :         }
    2433          11 :         pos = wpabuf_head(wps);
    2434          11 :         wsc_len = WPA_GET_BE16(pos);
    2435          11 :         if (wsc_len > wpabuf_len(wps) - 2) {
    2436           0 :                 wpa_printf(MSG_DEBUG, "WPS: Invalid WSC attribute length (%u) "
    2437             :                            "in Wi-Fi Handover Select Message", wsc_len);
    2438           0 :                 goto out;
    2439             :         }
    2440          11 :         pos += 2;
    2441             : 
    2442          11 :         wpa_hexdump(MSG_DEBUG,
    2443             :                     "WPS: WSC attributes in Wi-Fi Handover Select Message",
    2444             :                     pos, wsc_len);
    2445          11 :         if (wsc_len < wpabuf_len(wps) - 2) {
    2446           0 :                 wpa_hexdump(MSG_DEBUG,
    2447             :                             "WPS: Ignore extra data after WSC attributes",
    2448           0 :                             pos + wsc_len, wpabuf_len(wps) - 2 - wsc_len);
    2449             :         }
    2450             : 
    2451          11 :         wpabuf_set(&msg, pos, wsc_len);
    2452          11 :         ret = wps_parse_msg(&msg, &attr);
    2453          11 :         if (ret < 0) {
    2454           0 :                 wpa_printf(MSG_DEBUG, "WPS: Could not parse WSC attributes in "
    2455             :                            "Wi-Fi Handover Select Message");
    2456           0 :                 goto out;
    2457             :         }
    2458             : 
    2459          22 :         if (attr.oob_dev_password == NULL ||
    2460          11 :             attr.oob_dev_password_len < WPS_OOB_PUBKEY_HASH_LEN + 2) {
    2461           0 :                 wpa_printf(MSG_DEBUG, "WPS: No Out-of-Band Device Password "
    2462             :                            "included in Wi-Fi Handover Select Message");
    2463           0 :                 ret = -1;
    2464           0 :                 goto out;
    2465             :         }
    2466             : 
    2467          11 :         if (attr.ssid == NULL) {
    2468           0 :                 wpa_printf(MSG_DEBUG, "WPS: No SSID included in Wi-Fi Handover "
    2469             :                            "Select Message");
    2470           0 :                 ret = -1;
    2471           0 :                 goto out;
    2472             :         }
    2473             : 
    2474          11 :         wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID", attr.ssid, attr.ssid_len);
    2475             : 
    2476          11 :         if (attr.mac_addr) {
    2477          11 :                 bssid = attr.mac_addr;
    2478          66 :                 wpa_printf(MSG_DEBUG, "WPS: MAC Address (BSSID): " MACSTR,
    2479          66 :                            MAC2STR(bssid));
    2480             :         }
    2481             : 
    2482          11 :         if (attr.rf_bands)
    2483           8 :                 wpa_printf(MSG_DEBUG, "WPS: RF Bands: %d", *attr.rf_bands);
    2484             : 
    2485          11 :         if (attr.ap_channel) {
    2486           8 :                 u16 chan = WPA_GET_BE16(attr.ap_channel);
    2487             : 
    2488           8 :                 wpa_printf(MSG_DEBUG, "WPS: AP Channel: %d", chan);
    2489             : 
    2490          14 :                 if (chan >= 1 && chan <= 13 &&
    2491          12 :                     (attr.rf_bands == NULL || *attr.rf_bands & WPS_RF_24GHZ))
    2492           6 :                         freq = 2407 + 5 * chan;
    2493           3 :                 else if (chan == 14 &&
    2494           2 :                          (attr.rf_bands == NULL ||
    2495           1 :                           *attr.rf_bands & WPS_RF_24GHZ))
    2496           1 :                         freq = 2484;
    2497           2 :                 else if (chan >= 30 &&
    2498           2 :                          (attr.rf_bands == NULL ||
    2499           1 :                           *attr.rf_bands & WPS_RF_50GHZ))
    2500           1 :                         freq = 5000 + 5 * chan;
    2501             : 
    2502           8 :                 if (freq) {
    2503           8 :                         wpa_printf(MSG_DEBUG,
    2504             :                                    "WPS: AP indicated channel %u -> %u MHz",
    2505             :                                    chan, freq);
    2506             :                 }
    2507             :         }
    2508             : 
    2509          22 :         wpa_hexdump(MSG_DEBUG, "WPS: Out-of-Band Device Password",
    2510          11 :                     attr.oob_dev_password, attr.oob_dev_password_len);
    2511          11 :         dev_pw_id = WPA_GET_BE16(attr.oob_dev_password +
    2512             :                                  WPS_OOB_PUBKEY_HASH_LEN);
    2513          11 :         if (dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER) {
    2514           0 :                 wpa_printf(MSG_DEBUG, "WPS: Unexpected OOB Device Password ID "
    2515             :                            "%u in Wi-Fi Handover Select Message", dev_pw_id);
    2516           0 :                 ret = -1;
    2517           0 :                 goto out;
    2518             :         }
    2519          11 :         wpa_hexdump(MSG_DEBUG, "WPS: AP Public Key hash",
    2520          11 :                     attr.oob_dev_password, WPS_OOB_PUBKEY_HASH_LEN);
    2521             : 
    2522          11 :         ret = wpas_wps_start_nfc(wpa_s, NULL, bssid, NULL, dev_pw_id, 0,
    2523             :                                  attr.oob_dev_password,
    2524             :                                  attr.ssid, attr.ssid_len, freq);
    2525             : 
    2526             : out:
    2527          11 :         wpabuf_free(wps);
    2528          11 :         return ret;
    2529             : }
    2530             : 
    2531             : 
    2532          11 : int wpas_wps_nfc_report_handover(struct wpa_supplicant *wpa_s,
    2533             :                                  const struct wpabuf *req,
    2534             :                                  const struct wpabuf *sel)
    2535             : {
    2536          11 :         wpa_printf(MSG_DEBUG, "NFC: WPS connection handover reported");
    2537          11 :         wpa_hexdump_buf_key(MSG_DEBUG, "WPS: Carrier record in request", req);
    2538          11 :         wpa_hexdump_buf_key(MSG_DEBUG, "WPS: Carrier record in select", sel);
    2539          11 :         return wpas_wps_nfc_rx_handover_sel(wpa_s, sel);
    2540             : }
    2541             : 
    2542             : 
    2543           3 : int wpas_er_wps_nfc_report_handover(struct wpa_supplicant *wpa_s,
    2544             :                                     const struct wpabuf *req,
    2545             :                                     const struct wpabuf *sel)
    2546             : {
    2547             :         struct wpabuf *wps;
    2548           3 :         int ret = -1;
    2549             :         u16 wsc_len;
    2550             :         const u8 *pos;
    2551             :         struct wpabuf msg;
    2552             :         struct wps_parse_attr attr;
    2553             :         u16 dev_pw_id;
    2554             : 
    2555             :         /*
    2556             :          * Enrollee/station is always initiator of the NFC connection handover,
    2557             :          * so use the request message here to find Enrollee public key hash.
    2558             :          */
    2559           3 :         wps = ndef_parse_wifi(req);
    2560           3 :         if (wps == NULL)
    2561           0 :                 return -1;
    2562           3 :         wpa_printf(MSG_DEBUG, "WPS: Received application/vnd.wfa.wsc "
    2563             :                    "payload from NFC connection handover");
    2564           3 :         wpa_hexdump_buf(MSG_DEBUG, "WPS: NFC payload", wps);
    2565           3 :         if (wpabuf_len(wps) < 2) {
    2566           0 :                 wpa_printf(MSG_DEBUG, "WPS: Too short Wi-Fi Handover Request "
    2567             :                            "Message");
    2568           0 :                 goto out;
    2569             :         }
    2570           3 :         pos = wpabuf_head(wps);
    2571           3 :         wsc_len = WPA_GET_BE16(pos);
    2572           3 :         if (wsc_len > wpabuf_len(wps) - 2) {
    2573           0 :                 wpa_printf(MSG_DEBUG, "WPS: Invalid WSC attribute length (%u) "
    2574             :                            "in rt Wi-Fi Handover Request Message", wsc_len);
    2575           0 :                 goto out;
    2576             :         }
    2577           3 :         pos += 2;
    2578             : 
    2579           3 :         wpa_hexdump(MSG_DEBUG,
    2580             :                     "WPS: WSC attributes in Wi-Fi Handover Request Message",
    2581             :                     pos, wsc_len);
    2582           3 :         if (wsc_len < wpabuf_len(wps) - 2) {
    2583           0 :                 wpa_hexdump(MSG_DEBUG,
    2584             :                             "WPS: Ignore extra data after WSC attributes",
    2585           0 :                             pos + wsc_len, wpabuf_len(wps) - 2 - wsc_len);
    2586             :         }
    2587             : 
    2588           3 :         wpabuf_set(&msg, pos, wsc_len);
    2589           3 :         ret = wps_parse_msg(&msg, &attr);
    2590           3 :         if (ret < 0) {
    2591           0 :                 wpa_printf(MSG_DEBUG, "WPS: Could not parse WSC attributes in "
    2592             :                            "Wi-Fi Handover Request Message");
    2593           0 :                 goto out;
    2594             :         }
    2595             : 
    2596           6 :         if (attr.oob_dev_password == NULL ||
    2597           3 :             attr.oob_dev_password_len < WPS_OOB_PUBKEY_HASH_LEN + 2) {
    2598           0 :                 wpa_printf(MSG_DEBUG, "WPS: No Out-of-Band Device Password "
    2599             :                            "included in Wi-Fi Handover Request Message");
    2600           0 :                 ret = -1;
    2601           0 :                 goto out;
    2602             :         }
    2603             : 
    2604           3 :         if (attr.uuid_e == NULL) {
    2605           0 :                 wpa_printf(MSG_DEBUG, "WPS: No UUID-E included in Wi-Fi "
    2606             :                            "Handover Request Message");
    2607           0 :                 ret = -1;
    2608           0 :                 goto out;
    2609             :         }
    2610             : 
    2611           3 :         wpa_hexdump(MSG_DEBUG, "WPS: UUID-E", attr.uuid_e, WPS_UUID_LEN);
    2612             : 
    2613           6 :         wpa_hexdump(MSG_DEBUG, "WPS: Out-of-Band Device Password",
    2614           3 :                     attr.oob_dev_password, attr.oob_dev_password_len);
    2615           3 :         dev_pw_id = WPA_GET_BE16(attr.oob_dev_password +
    2616             :                                  WPS_OOB_PUBKEY_HASH_LEN);
    2617           3 :         if (dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER) {
    2618           0 :                 wpa_printf(MSG_DEBUG, "WPS: Unexpected OOB Device Password ID "
    2619             :                            "%u in Wi-Fi Handover Request Message", dev_pw_id);
    2620           0 :                 ret = -1;
    2621           0 :                 goto out;
    2622             :         }
    2623           3 :         wpa_hexdump(MSG_DEBUG, "WPS: Enrollee Public Key hash",
    2624           3 :                     attr.oob_dev_password, WPS_OOB_PUBKEY_HASH_LEN);
    2625             : 
    2626           3 :         ret = wps_registrar_add_nfc_pw_token(wpa_s->wps->registrar,
    2627             :                                              attr.oob_dev_password,
    2628             :                                              DEV_PW_NFC_CONNECTION_HANDOVER,
    2629             :                                              NULL, 0, 1);
    2630             : 
    2631             : out:
    2632           3 :         wpabuf_free(wps);
    2633           3 :         return ret;
    2634             : }
    2635             : 
    2636             : #endif /* CONFIG_WPS_NFC */
    2637             : 
    2638             : 
    2639        1048 : static void wpas_wps_dump_ap_info(struct wpa_supplicant *wpa_s)
    2640             : {
    2641             :         size_t i;
    2642             :         struct os_reltime now;
    2643             : 
    2644        1048 :         if (wpa_debug_level > MSG_DEBUG)
    2645         706 :                 return;
    2646             : 
    2647        1048 :         if (wpa_s->wps_ap == NULL)
    2648         706 :                 return;
    2649             : 
    2650         342 :         os_get_reltime(&now);
    2651             : 
    2652         711 :         for (i = 0; i < wpa_s->num_wps_ap; i++) {
    2653         369 :                 struct wps_ap_info *ap = &wpa_s->wps_ap[i];
    2654         369 :                 struct wpa_blacklist *e = wpa_blacklist_get(wpa_s, ap->bssid);
    2655             : 
    2656        2956 :                 wpa_printf(MSG_DEBUG, "WPS: AP[%d] " MACSTR " type=%d "
    2657             :                            "tries=%d last_attempt=%d sec ago blacklist=%d",
    2658        2214 :                            (int) i, MAC2STR(ap->bssid), ap->type, ap->tries,
    2659         369 :                            ap->last_attempt.sec > 0 ?
    2660           4 :                            (int) now.sec - (int) ap->last_attempt.sec : -1,
    2661             :                            e ? e->count : 0);
    2662             :         }
    2663             : }
    2664             : 
    2665             : 
    2666         538 : static struct wps_ap_info * wpas_wps_get_ap_info(struct wpa_supplicant *wpa_s,
    2667             :                                                  const u8 *bssid)
    2668             : {
    2669             :         size_t i;
    2670             : 
    2671         538 :         if (wpa_s->wps_ap == NULL)
    2672         250 :                 return NULL;
    2673             : 
    2674         323 :         for (i = 0; i < wpa_s->num_wps_ap; i++) {
    2675         303 :                 struct wps_ap_info *ap = &wpa_s->wps_ap[i];
    2676         303 :                 if (os_memcmp(ap->bssid, bssid, ETH_ALEN) == 0)
    2677         268 :                         return ap;
    2678             :         }
    2679             : 
    2680          20 :         return NULL;
    2681             : }
    2682             : 
    2683             : 
    2684        1204 : static void wpas_wps_update_ap_info_bss(struct wpa_supplicant *wpa_s,
    2685             :                                         struct wpa_scan_res *res)
    2686             : {
    2687             :         struct wpabuf *wps;
    2688             :         enum wps_ap_info_type type;
    2689             :         struct wps_ap_info *ap;
    2690             :         int r;
    2691             : 
    2692        1204 :         if (wpa_scan_get_vendor_ie(res, WPS_IE_VENDOR_TYPE) == NULL)
    2693         799 :                 return;
    2694             : 
    2695         405 :         wps = wpa_scan_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE);
    2696         405 :         if (wps == NULL)
    2697           0 :                 return;
    2698             : 
    2699         405 :         r = wps_is_addr_authorized(wps, wpa_s->own_addr, 1);
    2700         405 :         if (r == 2)
    2701          59 :                 type = WPS_AP_SEL_REG_OUR;
    2702         346 :         else if (r == 1)
    2703         140 :                 type = WPS_AP_SEL_REG;
    2704             :         else
    2705         206 :                 type = WPS_AP_NOT_SEL_REG;
    2706             : 
    2707         405 :         wpabuf_free(wps);
    2708             : 
    2709         405 :         ap = wpas_wps_get_ap_info(wpa_s, res->bssid);
    2710         405 :         if (ap) {
    2711         135 :                 if (ap->type != type) {
    2712         222 :                         wpa_printf(MSG_DEBUG, "WPS: AP " MACSTR
    2713             :                                    " changed type %d -> %d",
    2714         222 :                                    MAC2STR(res->bssid), ap->type, type);
    2715          37 :                         ap->type = type;
    2716          37 :                         if (type != WPS_AP_NOT_SEL_REG)
    2717          11 :                                 wpa_blacklist_del(wpa_s, ap->bssid);
    2718             :                 }
    2719         135 :                 return;
    2720             :         }
    2721             : 
    2722         270 :         ap = os_realloc_array(wpa_s->wps_ap, wpa_s->num_wps_ap + 1,
    2723             :                               sizeof(struct wps_ap_info));
    2724         270 :         if (ap == NULL)
    2725           0 :                 return;
    2726             : 
    2727         270 :         wpa_s->wps_ap = ap;
    2728         270 :         ap = &wpa_s->wps_ap[wpa_s->num_wps_ap];
    2729         270 :         wpa_s->num_wps_ap++;
    2730             : 
    2731         270 :         os_memset(ap, 0, sizeof(*ap));
    2732         270 :         os_memcpy(ap->bssid, res->bssid, ETH_ALEN);
    2733         270 :         ap->type = type;
    2734        1620 :         wpa_printf(MSG_DEBUG, "WPS: AP " MACSTR " type %d added",
    2735        1620 :                    MAC2STR(ap->bssid), ap->type);
    2736             : }
    2737             : 
    2738             : 
    2739        1048 : void wpas_wps_update_ap_info(struct wpa_supplicant *wpa_s,
    2740             :                              struct wpa_scan_results *scan_res)
    2741             : {
    2742             :         size_t i;
    2743             : 
    2744        2252 :         for (i = 0; i < scan_res->num; i++)
    2745        1204 :                 wpas_wps_update_ap_info_bss(wpa_s, scan_res->res[i]);
    2746             : 
    2747        1048 :         wpas_wps_dump_ap_info(wpa_s);
    2748        1048 : }
    2749             : 
    2750             : 
    2751        1046 : void wpas_wps_notify_assoc(struct wpa_supplicant *wpa_s, const u8 *bssid)
    2752             : {
    2753             :         struct wps_ap_info *ap;
    2754             : 
    2755        1046 :         wpa_s->after_wps = 0;
    2756             : 
    2757        1046 :         if (!wpa_s->wps_ap_iter)
    2758         913 :                 return;
    2759         133 :         ap = wpas_wps_get_ap_info(wpa_s, bssid);
    2760         133 :         if (ap == NULL)
    2761           0 :                 return;
    2762         133 :         ap->tries++;
    2763         133 :         os_get_reltime(&ap->last_attempt);
    2764             : }

Generated by: LCOV version 1.10