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 1475438200 Lines: 1276 1517 84.1 %
Date: 2016-10-02 Functions: 76 80 95.0 %

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

Generated by: LCOV version 1.10