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 1443382998 Lines: 1280 1505 85.0 %
Date: 2015-09-27 Functions: 77 79 97.5 %

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

Generated by: LCOV version 1.10