LCOV - code coverage report
Current view: top level - src/wps - wps_registrar.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1393793999 Lines: 1537 1940 79.2 %
Date: 2014-03-02 Functions: 112 113 99.1 %
Branches: 766 1200 63.8 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Wi-Fi Protected Setup - Registrar
       3                 :            :  * Copyright (c) 2008-2013, 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 "utils/includes.h"
      10                 :            : 
      11                 :            : #include "utils/common.h"
      12                 :            : #include "utils/base64.h"
      13                 :            : #include "utils/eloop.h"
      14                 :            : #include "utils/uuid.h"
      15                 :            : #include "utils/list.h"
      16                 :            : #include "crypto/crypto.h"
      17                 :            : #include "crypto/sha256.h"
      18                 :            : #include "crypto/random.h"
      19                 :            : #include "common/ieee802_11_defs.h"
      20                 :            : #include "wps_i.h"
      21                 :            : #include "wps_dev_attr.h"
      22                 :            : #include "wps_upnp.h"
      23                 :            : #include "wps_upnp_i.h"
      24                 :            : 
      25                 :            : #ifndef CONFIG_WPS_STRICT
      26                 :            : #define WPS_WORKAROUNDS
      27                 :            : #endif /* CONFIG_WPS_STRICT */
      28                 :            : 
      29                 :            : #ifdef CONFIG_WPS_NFC
      30                 :            : 
      31                 :            : struct wps_nfc_pw_token {
      32                 :            :         struct dl_list list;
      33                 :            :         u8 pubkey_hash[WPS_OOB_PUBKEY_HASH_LEN];
      34                 :            :         unsigned int peer_pk_hash_known:1;
      35                 :            :         u16 pw_id;
      36                 :            :         u8 dev_pw[WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1];
      37                 :            :         size_t dev_pw_len;
      38                 :            :         int pk_hash_provided_oob; /* whether own PK hash was provided OOB */
      39                 :            : };
      40                 :            : 
      41                 :            : 
      42                 :          1 : static void wps_remove_nfc_pw_token(struct wps_nfc_pw_token *token)
      43                 :            : {
      44                 :          1 :         dl_list_del(&token->list);
      45                 :          1 :         os_free(token);
      46                 :          1 : }
      47                 :            : 
      48                 :            : 
      49                 :        198 : static void wps_free_nfc_pw_tokens(struct dl_list *tokens, u16 pw_id)
      50                 :            : {
      51                 :            :         struct wps_nfc_pw_token *token, *prev;
      52         [ +  + ]:        199 :         dl_list_for_each_safe(token, prev, tokens, struct wps_nfc_pw_token,
      53                 :            :                               list) {
      54 [ -  + ][ #  # ]:          1 :                 if (pw_id == 0 || pw_id == token->pw_id)
      55                 :          1 :                         wps_remove_nfc_pw_token(token);
      56                 :            :         }
      57                 :        198 : }
      58                 :            : 
      59                 :            : 
      60                 :         29 : static struct wps_nfc_pw_token * wps_get_nfc_pw_token(struct dl_list *tokens,
      61                 :            :                                                       u16 pw_id)
      62                 :            : {
      63                 :            :         struct wps_nfc_pw_token *token;
      64         [ +  + ]:         29 :         dl_list_for_each(token, tokens, struct wps_nfc_pw_token, list) {
      65         [ +  - ]:         23 :                 if (pw_id == token->pw_id)
      66                 :         23 :                         return token;
      67                 :            :         }
      68                 :         29 :         return NULL;
      69                 :            : }
      70                 :            : 
      71                 :            : #else /* CONFIG_WPS_NFC */
      72                 :            : 
      73                 :            : #define wps_free_nfc_pw_tokens(t, p) do { } while (0)
      74                 :            : 
      75                 :            : #endif /* CONFIG_WPS_NFC */
      76                 :            : 
      77                 :            : 
      78                 :            : struct wps_uuid_pin {
      79                 :            :         struct dl_list list;
      80                 :            :         u8 uuid[WPS_UUID_LEN];
      81                 :            :         int wildcard_uuid;
      82                 :            :         u8 *pin;
      83                 :            :         size_t pin_len;
      84                 :            : #define PIN_LOCKED BIT(0)
      85                 :            : #define PIN_EXPIRES BIT(1)
      86                 :            :         int flags;
      87                 :            :         struct os_reltime expiration;
      88                 :            :         u8 enrollee_addr[ETH_ALEN];
      89                 :            : };
      90                 :            : 
      91                 :            : 
      92                 :        106 : static void wps_free_pin(struct wps_uuid_pin *pin)
      93                 :            : {
      94                 :        106 :         os_free(pin->pin);
      95                 :        106 :         os_free(pin);
      96                 :        106 : }
      97                 :            : 
      98                 :            : 
      99                 :        106 : static void wps_remove_pin(struct wps_uuid_pin *pin)
     100                 :            : {
     101                 :        106 :         dl_list_del(&pin->list);
     102                 :        106 :         wps_free_pin(pin);
     103                 :        106 : }
     104                 :            : 
     105                 :            : 
     106                 :        175 : static void wps_free_pins(struct dl_list *pins)
     107                 :            : {
     108                 :            :         struct wps_uuid_pin *pin, *prev;
     109         [ +  + ]:        187 :         dl_list_for_each_safe(pin, prev, pins, struct wps_uuid_pin, list)
     110                 :         12 :                 wps_remove_pin(pin);
     111                 :        175 : }
     112                 :            : 
     113                 :            : 
     114                 :            : struct wps_pbc_session {
     115                 :            :         struct wps_pbc_session *next;
     116                 :            :         u8 addr[ETH_ALEN];
     117                 :            :         u8 uuid_e[WPS_UUID_LEN];
     118                 :            :         struct os_reltime timestamp;
     119                 :            : };
     120                 :            : 
     121                 :            : 
     122                 :        175 : static void wps_free_pbc_sessions(struct wps_pbc_session *pbc)
     123                 :            : {
     124                 :            :         struct wps_pbc_session *prev;
     125                 :            : 
     126         [ +  + ]:        180 :         while (pbc) {
     127                 :          5 :                 prev = pbc;
     128                 :          5 :                 pbc = pbc->next;
     129                 :          5 :                 os_free(prev);
     130                 :            :         }
     131                 :        175 : }
     132                 :            : 
     133                 :            : 
     134                 :            : struct wps_registrar_device {
     135                 :            :         struct wps_registrar_device *next;
     136                 :            :         struct wps_device_data dev;
     137                 :            :         u8 uuid[WPS_UUID_LEN];
     138                 :            : };
     139                 :            : 
     140                 :            : 
     141                 :            : struct wps_registrar {
     142                 :            :         struct wps_context *wps;
     143                 :            : 
     144                 :            :         int pbc;
     145                 :            :         int selected_registrar;
     146                 :            : 
     147                 :            :         int (*new_psk_cb)(void *ctx, const u8 *mac_addr, const u8 *p2p_dev_addr,
     148                 :            :                           const u8 *psk, size_t psk_len);
     149                 :            :         int (*set_ie_cb)(void *ctx, struct wpabuf *beacon_ie,
     150                 :            :                          struct wpabuf *probe_resp_ie);
     151                 :            :         void (*pin_needed_cb)(void *ctx, const u8 *uuid_e,
     152                 :            :                               const struct wps_device_data *dev);
     153                 :            :         void (*reg_success_cb)(void *ctx, const u8 *mac_addr,
     154                 :            :                                const u8 *uuid_e, const u8 *dev_pw,
     155                 :            :                                size_t dev_pw_len);
     156                 :            :         void (*set_sel_reg_cb)(void *ctx, int sel_reg, u16 dev_passwd_id,
     157                 :            :                                u16 sel_reg_config_methods);
     158                 :            :         void (*enrollee_seen_cb)(void *ctx, const u8 *addr, const u8 *uuid_e,
     159                 :            :                                  const u8 *pri_dev_type, u16 config_methods,
     160                 :            :                                  u16 dev_password_id, u8 request_type,
     161                 :            :                                  const char *dev_name);
     162                 :            :         void *cb_ctx;
     163                 :            : 
     164                 :            :         struct dl_list pins;
     165                 :            :         struct dl_list nfc_pw_tokens;
     166                 :            :         struct wps_pbc_session *pbc_sessions;
     167                 :            : 
     168                 :            :         int skip_cred_build;
     169                 :            :         struct wpabuf *extra_cred;
     170                 :            :         int disable_auto_conf;
     171                 :            :         int sel_reg_union;
     172                 :            :         int sel_reg_dev_password_id_override;
     173                 :            :         int sel_reg_config_methods_override;
     174                 :            :         int static_wep_only;
     175                 :            :         int dualband;
     176                 :            :         int force_per_enrollee_psk;
     177                 :            : 
     178                 :            :         struct wps_registrar_device *devices;
     179                 :            : 
     180                 :            :         int force_pbc_overlap;
     181                 :            : 
     182                 :            :         u8 authorized_macs[WPS_MAX_AUTHORIZED_MACS][ETH_ALEN];
     183                 :            :         u8 authorized_macs_union[WPS_MAX_AUTHORIZED_MACS][ETH_ALEN];
     184                 :            : 
     185                 :            :         u8 p2p_dev_addr[ETH_ALEN];
     186                 :            : 
     187                 :            :         u8 pbc_ignore_uuid[WPS_UUID_LEN];
     188                 :            : #ifdef WPS_WORKAROUNDS
     189                 :            :         struct os_reltime pbc_ignore_start;
     190                 :            : #endif /* WPS_WORKAROUNDS */
     191                 :            : };
     192                 :            : 
     193                 :            : 
     194                 :            : static int wps_set_ie(struct wps_registrar *reg);
     195                 :            : static void wps_registrar_pbc_timeout(void *eloop_ctx, void *timeout_ctx);
     196                 :            : static void wps_registrar_set_selected_timeout(void *eloop_ctx,
     197                 :            :                                                void *timeout_ctx);
     198                 :            : static void wps_registrar_remove_pin(struct wps_registrar *reg,
     199                 :            :                                      struct wps_uuid_pin *pin);
     200                 :            : 
     201                 :            : 
     202                 :        150 : static void wps_registrar_add_authorized_mac(struct wps_registrar *reg,
     203                 :            :                                              const u8 *addr)
     204                 :            : {
     205                 :            :         int i;
     206                 :        150 :         wpa_printf(MSG_DEBUG, "WPS: Add authorized MAC " MACSTR,
     207                 :        900 :                    MAC2STR(addr));
     208         [ +  + ]:        850 :         for (i = 0; i < WPS_MAX_AUTHORIZED_MACS; i++)
     209         [ +  + ]:        710 :                 if (os_memcmp(reg->authorized_macs[i], addr, ETH_ALEN) == 0) {
     210                 :         10 :                         wpa_printf(MSG_DEBUG, "WPS: Authorized MAC was "
     211                 :            :                                    "already in the list");
     212                 :        150 :                         return; /* already in list */
     213                 :            :                 }
     214         [ +  + ]:        700 :         for (i = WPS_MAX_AUTHORIZED_MACS - 1; i > 0; i--)
     215                 :        560 :                 os_memcpy(reg->authorized_macs[i], reg->authorized_macs[i - 1],
     216                 :            :                           ETH_ALEN);
     217                 :        140 :         os_memcpy(reg->authorized_macs[0], addr, ETH_ALEN);
     218                 :        140 :         wpa_hexdump(MSG_DEBUG, "WPS: Authorized MACs",
     219                 :        140 :                     (u8 *) reg->authorized_macs, sizeof(reg->authorized_macs));
     220                 :            : }
     221                 :            : 
     222                 :            : 
     223                 :        136 : static void wps_registrar_remove_authorized_mac(struct wps_registrar *reg,
     224                 :            :                                                 const u8 *addr)
     225                 :            : {
     226                 :            :         int i;
     227                 :        136 :         wpa_printf(MSG_DEBUG, "WPS: Remove authorized MAC " MACSTR,
     228                 :        816 :                    MAC2STR(addr));
     229         [ +  + ]:        141 :         for (i = 0; i < WPS_MAX_AUTHORIZED_MACS; i++) {
     230         [ +  + ]:        140 :                 if (os_memcmp(reg->authorized_macs, addr, ETH_ALEN) == 0)
     231                 :        135 :                         break;
     232                 :            :         }
     233         [ +  + ]:        136 :         if (i == WPS_MAX_AUTHORIZED_MACS) {
     234                 :          1 :                 wpa_printf(MSG_DEBUG, "WPS: Authorized MAC was not in the "
     235                 :            :                            "list");
     236                 :        136 :                 return; /* not in the list */
     237                 :            :         }
     238         [ +  + ]:        675 :         for (; i + 1 < WPS_MAX_AUTHORIZED_MACS; i++)
     239                 :        540 :                 os_memcpy(reg->authorized_macs[i], reg->authorized_macs[i + 1],
     240                 :            :                           ETH_ALEN);
     241                 :        135 :         os_memset(reg->authorized_macs[WPS_MAX_AUTHORIZED_MACS - 1], 0,
     242                 :            :                   ETH_ALEN);
     243                 :        135 :         wpa_hexdump(MSG_DEBUG, "WPS: Authorized MACs",
     244                 :        135 :                     (u8 *) reg->authorized_macs, sizeof(reg->authorized_macs));
     245                 :            : }
     246                 :            : 
     247                 :            : 
     248                 :        175 : static void wps_free_devices(struct wps_registrar_device *dev)
     249                 :            : {
     250                 :            :         struct wps_registrar_device *prev;
     251                 :            : 
     252         [ +  + ]:        300 :         while (dev) {
     253                 :        125 :                 prev = dev;
     254                 :        125 :                 dev = dev->next;
     255                 :        125 :                 wps_device_data_free(&prev->dev);
     256                 :        125 :                 os_free(prev);
     257                 :            :         }
     258                 :        175 : }
     259                 :            : 
     260                 :            : 
     261                 :        139 : static struct wps_registrar_device * wps_device_get(struct wps_registrar *reg,
     262                 :            :                                                     const u8 *addr)
     263                 :            : {
     264                 :            :         struct wps_registrar_device *dev;
     265                 :            : 
     266         [ +  + ]:        176 :         for (dev = reg->devices; dev; dev = dev->next) {
     267         [ +  + ]:         48 :                 if (os_memcmp(dev->dev.mac_addr, addr, ETH_ALEN) == 0)
     268                 :         11 :                         return dev;
     269                 :            :         }
     270                 :        139 :         return NULL;
     271                 :            : }
     272                 :            : 
     273                 :            : 
     274                 :        135 : static void wps_device_clone_data(struct wps_device_data *dst,
     275                 :            :                                   struct wps_device_data *src)
     276                 :            : {
     277                 :        135 :         os_memcpy(dst->mac_addr, src->mac_addr, ETH_ALEN);
     278                 :        135 :         os_memcpy(dst->pri_dev_type, src->pri_dev_type, WPS_DEV_TYPE_LEN);
     279                 :            : 
     280                 :            : #define WPS_STRDUP(n) \
     281                 :            :         os_free(dst->n); \
     282                 :            :         dst->n = src->n ? os_strdup(src->n) : NULL
     283                 :            : 
     284         [ +  - ]:        135 :         WPS_STRDUP(device_name);
     285         [ +  - ]:        135 :         WPS_STRDUP(manufacturer);
     286         [ +  - ]:        135 :         WPS_STRDUP(model_name);
     287         [ +  - ]:        135 :         WPS_STRDUP(model_number);
     288         [ +  - ]:        135 :         WPS_STRDUP(serial_number);
     289                 :            : #undef WPS_STRDUP
     290                 :        135 : }
     291                 :            : 
     292                 :            : 
     293                 :        135 : int wps_device_store(struct wps_registrar *reg,
     294                 :            :                      struct wps_device_data *dev, const u8 *uuid)
     295                 :            : {
     296                 :            :         struct wps_registrar_device *d;
     297                 :            : 
     298                 :        135 :         d = wps_device_get(reg, dev->mac_addr);
     299         [ +  + ]:        135 :         if (d == NULL) {
     300                 :        125 :                 d = os_zalloc(sizeof(*d));
     301         [ -  + ]:        125 :                 if (d == NULL)
     302                 :          0 :                         return -1;
     303                 :        125 :                 d->next = reg->devices;
     304                 :        125 :                 reg->devices = d;
     305                 :            :         }
     306                 :            : 
     307                 :        135 :         wps_device_clone_data(&d->dev, dev);
     308                 :        135 :         os_memcpy(d->uuid, uuid, WPS_UUID_LEN);
     309                 :            : 
     310                 :        135 :         return 0;
     311                 :            : }
     312                 :            : 
     313                 :            : 
     314                 :         38 : static void wps_registrar_add_pbc_session(struct wps_registrar *reg,
     315                 :            :                                           const u8 *addr, const u8 *uuid_e)
     316                 :            : {
     317                 :         38 :         struct wps_pbc_session *pbc, *prev = NULL;
     318                 :            :         struct os_reltime now;
     319                 :            : 
     320                 :         38 :         os_get_reltime(&now);
     321                 :            : 
     322                 :         38 :         pbc = reg->pbc_sessions;
     323         [ +  + ]:         39 :         while (pbc) {
     324 [ +  + ][ +  - ]:         18 :                 if (os_memcmp(pbc->addr, addr, ETH_ALEN) == 0 &&
     325                 :         17 :                     os_memcmp(pbc->uuid_e, uuid_e, WPS_UUID_LEN) == 0) {
     326         [ -  + ]:         17 :                         if (prev)
     327                 :          0 :                                 prev->next = pbc->next;
     328                 :            :                         else
     329                 :         17 :                                 reg->pbc_sessions = pbc->next;
     330                 :         17 :                         break;
     331                 :            :                 }
     332                 :          1 :                 prev = pbc;
     333                 :          1 :                 pbc = pbc->next;
     334                 :            :         }
     335                 :            : 
     336         [ +  + ]:         38 :         if (!pbc) {
     337                 :         21 :                 pbc = os_zalloc(sizeof(*pbc));
     338         [ -  + ]:         21 :                 if (pbc == NULL)
     339                 :         38 :                         return;
     340                 :         21 :                 os_memcpy(pbc->addr, addr, ETH_ALEN);
     341         [ +  - ]:         21 :                 if (uuid_e)
     342                 :         21 :                         os_memcpy(pbc->uuid_e, uuid_e, WPS_UUID_LEN);
     343                 :            :         }
     344                 :            : 
     345                 :         38 :         pbc->next = reg->pbc_sessions;
     346                 :         38 :         reg->pbc_sessions = pbc;
     347                 :         38 :         pbc->timestamp = now;
     348                 :            : 
     349                 :            :         /* remove entries that have timed out */
     350                 :         38 :         prev = pbc;
     351                 :         38 :         pbc = pbc->next;
     352                 :            : 
     353         [ +  + ]:         39 :         while (pbc) {
     354         [ -  + ]:          1 :                 if (os_reltime_expired(&now, &pbc->timestamp,
     355                 :            :                                        WPS_PBC_WALK_TIME)) {
     356                 :          0 :                         prev->next = NULL;
     357                 :          0 :                         wps_free_pbc_sessions(pbc);
     358                 :          0 :                         break;
     359                 :            :                 }
     360                 :          1 :                 prev = pbc;
     361                 :          1 :                 pbc = pbc->next;
     362                 :            :         }
     363                 :            : }
     364                 :            : 
     365                 :            : 
     366                 :         16 : static void wps_registrar_remove_pbc_session(struct wps_registrar *reg,
     367                 :            :                                              const u8 *uuid_e,
     368                 :            :                                              const u8 *p2p_dev_addr)
     369                 :            : {
     370                 :         16 :         struct wps_pbc_session *pbc, *prev = NULL, *tmp;
     371                 :            : 
     372                 :         16 :         pbc = reg->pbc_sessions;
     373         [ +  + ]:         32 :         while (pbc) {
     374 [ -  + ][ #  # ]:         16 :                 if (os_memcmp(pbc->uuid_e, uuid_e, WPS_UUID_LEN) == 0 ||
     375 [ #  # ][ #  # ]:          0 :                     (p2p_dev_addr && !is_zero_ether_addr(reg->p2p_dev_addr) &&
     376                 :          0 :                      os_memcmp(reg->p2p_dev_addr, p2p_dev_addr, ETH_ALEN) ==
     377                 :            :                      0)) {
     378         [ -  + ]:         16 :                         if (prev)
     379                 :          0 :                                 prev->next = pbc->next;
     380                 :            :                         else
     381                 :         16 :                                 reg->pbc_sessions = pbc->next;
     382                 :         16 :                         tmp = pbc;
     383                 :         16 :                         pbc = pbc->next;
     384                 :         16 :                         wpa_printf(MSG_DEBUG, "WPS: Removing PBC session for "
     385                 :         96 :                                    "addr=" MACSTR, MAC2STR(tmp->addr));
     386                 :         16 :                         wpa_hexdump(MSG_DEBUG, "WPS: Removed UUID-E",
     387                 :         16 :                                     tmp->uuid_e, WPS_UUID_LEN);
     388                 :         16 :                         os_free(tmp);
     389                 :         16 :                         continue;
     390                 :            :                 }
     391                 :          0 :                 prev = pbc;
     392                 :          0 :                 pbc = pbc->next;
     393                 :            :         }
     394                 :         16 : }
     395                 :            : 
     396                 :            : 
     397                 :         58 : int wps_registrar_pbc_overlap(struct wps_registrar *reg,
     398                 :            :                               const u8 *addr, const u8 *uuid_e)
     399                 :            : {
     400                 :         58 :         int count = 0;
     401                 :            :         struct wps_pbc_session *pbc;
     402                 :         58 :         struct wps_pbc_session *first = NULL;
     403                 :            :         struct os_reltime now;
     404                 :            : 
     405                 :         58 :         os_get_reltime(&now);
     406                 :            : 
     407                 :         58 :         wpa_printf(MSG_DEBUG, "WPS: Checking active PBC sessions for overlap");
     408                 :            : 
     409         [ +  + ]:         58 :         if (uuid_e) {
     410                 :         38 :                 wpa_printf(MSG_DEBUG, "WPS: Add one for the requested UUID");
     411                 :         38 :                 wpa_hexdump(MSG_DEBUG, "WPS: Requested UUID",
     412                 :            :                             uuid_e, WPS_UUID_LEN);
     413                 :         38 :                 count++;
     414                 :            :         }
     415                 :            : 
     416         [ +  + ]:        101 :         for (pbc = reg->pbc_sessions; pbc; pbc = pbc->next) {
     417                 :         43 :                 wpa_printf(MSG_DEBUG, "WPS: Consider PBC session with " MACSTR,
     418                 :        258 :                            MAC2STR(pbc->addr));
     419                 :         43 :                 wpa_hexdump(MSG_DEBUG, "WPS: UUID-E",
     420                 :         43 :                             pbc->uuid_e, WPS_UUID_LEN);
     421         [ -  + ]:         43 :                 if (os_reltime_expired(&now, &pbc->timestamp,
     422                 :            :                                        WPS_PBC_WALK_TIME)) {
     423                 :          0 :                         wpa_printf(MSG_DEBUG, "WPS: PBC walk time has expired");
     424                 :          0 :                         break;
     425                 :            :                 }
     426 [ +  + ][ -  + ]:         43 :                 if (first &&
     427                 :          2 :                     os_memcmp(pbc->uuid_e, first->uuid_e, WPS_UUID_LEN) == 0) {
     428                 :          0 :                         wpa_printf(MSG_DEBUG, "WPS: Same Enrollee");
     429                 :          0 :                         continue; /* same Enrollee */
     430                 :            :                 }
     431 [ +  + ][ +  + ]:         43 :                 if (uuid_e == NULL ||
     432                 :         39 :                     os_memcmp(uuid_e, pbc->uuid_e, WPS_UUID_LEN)) {
     433                 :          5 :                         wpa_printf(MSG_DEBUG, "WPS: New Enrollee");
     434                 :          5 :                         count++;
     435                 :            :                 }
     436         [ +  + ]:         43 :                 if (first == NULL)
     437                 :         41 :                         first = pbc;
     438                 :            :         }
     439                 :            : 
     440                 :         58 :         wpa_printf(MSG_DEBUG, "WPS: %u active PBC session(s) found", count);
     441                 :            : 
     442                 :         58 :         return count > 1 ? 1 : 0;
     443                 :            : }
     444                 :            : 
     445                 :            : 
     446                 :        978 : static int wps_build_wps_state(struct wps_context *wps, struct wpabuf *msg)
     447                 :            : {
     448                 :        978 :         wpa_printf(MSG_DEBUG, "WPS:  * Wi-Fi Protected Setup State (%d)",
     449                 :        978 :                    wps->wps_state);
     450                 :        978 :         wpabuf_put_be16(msg, ATTR_WPS_STATE);
     451                 :        978 :         wpabuf_put_be16(msg, 1);
     452                 :        978 :         wpabuf_put_u8(msg, wps->wps_state);
     453                 :        978 :         return 0;
     454                 :            : }
     455                 :            : 
     456                 :            : 
     457                 :            : #ifdef CONFIG_WPS_UPNP
     458                 :         50 : static void wps_registrar_free_pending_m2(struct wps_context *wps)
     459                 :            : {
     460                 :         50 :         struct upnp_pending_message *p, *p2, *prev = NULL;
     461                 :         50 :         p = wps->upnp_msgs;
     462         [ +  + ]:         80 :         while (p) {
     463 [ +  - ][ -  + ]:         30 :                 if (p->type == WPS_M2 || p->type == WPS_M2D) {
     464         [ #  # ]:          0 :                         if (prev == NULL)
     465                 :          0 :                                 wps->upnp_msgs = p->next;
     466                 :            :                         else
     467                 :          0 :                                 prev->next = p->next;
     468                 :          0 :                         wpa_printf(MSG_DEBUG, "WPS UPnP: Drop pending M2/M2D");
     469                 :          0 :                         p2 = p;
     470                 :          0 :                         p = p->next;
     471                 :          0 :                         wpabuf_free(p2->msg);
     472                 :          0 :                         os_free(p2);
     473                 :          0 :                         continue;
     474                 :            :                 }
     475                 :         30 :                 prev = p;
     476                 :         30 :                 p = p->next;
     477                 :            :         }
     478                 :         50 : }
     479                 :            : #endif /* CONFIG_WPS_UPNP */
     480                 :            : 
     481                 :            : 
     482                 :        978 : static int wps_build_ap_setup_locked(struct wps_context *wps,
     483                 :            :                                      struct wpabuf *msg)
     484                 :            : {
     485 [ +  + ][ +  + ]:        978 :         if (wps->ap_setup_locked && wps->ap_setup_locked != 2) {
     486                 :         10 :                 wpa_printf(MSG_DEBUG, "WPS:  * AP Setup Locked");
     487                 :         10 :                 wpabuf_put_be16(msg, ATTR_AP_SETUP_LOCKED);
     488                 :         10 :                 wpabuf_put_be16(msg, 1);
     489                 :         10 :                 wpabuf_put_u8(msg, 1);
     490                 :            :         }
     491                 :        978 :         return 0;
     492                 :            : }
     493                 :            : 
     494                 :            : 
     495                 :        978 : static int wps_build_selected_registrar(struct wps_registrar *reg,
     496                 :            :                                         struct wpabuf *msg)
     497                 :            : {
     498         [ +  + ]:        978 :         if (!reg->sel_reg_union)
     499                 :        590 :                 return 0;
     500                 :        388 :         wpa_printf(MSG_DEBUG, "WPS:  * Selected Registrar");
     501                 :        388 :         wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR);
     502                 :        388 :         wpabuf_put_be16(msg, 1);
     503                 :        388 :         wpabuf_put_u8(msg, 1);
     504                 :        978 :         return 0;
     505                 :            : }
     506                 :            : 
     507                 :            : 
     508                 :        978 : static int wps_build_sel_reg_dev_password_id(struct wps_registrar *reg,
     509                 :            :                                              struct wpabuf *msg)
     510                 :            : {
     511         [ +  + ]:        978 :         u16 id = reg->pbc ? DEV_PW_PUSHBUTTON : DEV_PW_DEFAULT;
     512         [ +  + ]:        978 :         if (!reg->sel_reg_union)
     513                 :        590 :                 return 0;
     514         [ +  + ]:        388 :         if (reg->sel_reg_dev_password_id_override >= 0)
     515                 :        100 :                 id = reg->sel_reg_dev_password_id_override;
     516                 :        388 :         wpa_printf(MSG_DEBUG, "WPS:  * Device Password ID (%d)", id);
     517                 :        388 :         wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID);
     518                 :        388 :         wpabuf_put_be16(msg, 2);
     519                 :        388 :         wpabuf_put_be16(msg, id);
     520                 :        978 :         return 0;
     521                 :            : }
     522                 :            : 
     523                 :            : 
     524                 :        489 : static int wps_build_sel_pbc_reg_uuid_e(struct wps_registrar *reg,
     525                 :            :                                         struct wpabuf *msg)
     526                 :            : {
     527         [ +  + ]:        489 :         u16 id = reg->pbc ? DEV_PW_PUSHBUTTON : DEV_PW_DEFAULT;
     528         [ +  + ]:        489 :         if (!reg->sel_reg_union)
     529                 :        295 :                 return 0;
     530         [ +  + ]:        194 :         if (reg->sel_reg_dev_password_id_override >= 0)
     531                 :         50 :                 id = reg->sel_reg_dev_password_id_override;
     532 [ +  + ][ +  + ]:        194 :         if (id != DEV_PW_PUSHBUTTON || !reg->dualband)
     533                 :        192 :                 return 0;
     534                 :        489 :         return wps_build_uuid_e(msg, reg->wps->uuid);
     535                 :            : }
     536                 :            : 
     537                 :            : 
     538                 :         62 : static void wps_set_pushbutton(u16 *methods, u16 conf_methods)
     539                 :            : {
     540                 :         62 :         *methods |= WPS_CONFIG_PUSHBUTTON;
     541                 :            : #ifdef CONFIG_WPS2
     542         [ -  + ]:         62 :         if ((conf_methods & WPS_CONFIG_VIRT_PUSHBUTTON) ==
     543                 :            :             WPS_CONFIG_VIRT_PUSHBUTTON)
     544                 :          0 :                 *methods |= WPS_CONFIG_VIRT_PUSHBUTTON;
     545         [ -  + ]:         62 :         if ((conf_methods & WPS_CONFIG_PHY_PUSHBUTTON) ==
     546                 :            :             WPS_CONFIG_PHY_PUSHBUTTON)
     547                 :          0 :                 *methods |= WPS_CONFIG_PHY_PUSHBUTTON;
     548         [ +  - ]:         62 :         if ((*methods & WPS_CONFIG_VIRT_PUSHBUTTON) !=
     549         [ +  - ]:         62 :             WPS_CONFIG_VIRT_PUSHBUTTON &&
     550                 :         62 :             (*methods & WPS_CONFIG_PHY_PUSHBUTTON) !=
     551                 :            :             WPS_CONFIG_PHY_PUSHBUTTON) {
     552                 :            :                 /*
     553                 :            :                  * Required to include virtual/physical flag, but we were not
     554                 :            :                  * configured with push button type, so have to default to one
     555                 :            :                  * of them.
     556                 :            :                  */
     557                 :         62 :                 *methods |= WPS_CONFIG_PHY_PUSHBUTTON;
     558                 :            :         }
     559                 :            : #endif /* CONFIG_WPS2 */
     560                 :         62 : }
     561                 :            : 
     562                 :            : 
     563                 :        978 : static int wps_build_sel_reg_config_methods(struct wps_registrar *reg,
     564                 :            :                                             struct wpabuf *msg)
     565                 :            : {
     566                 :            :         u16 methods;
     567         [ +  + ]:        978 :         if (!reg->sel_reg_union)
     568                 :        590 :                 return 0;
     569                 :        388 :         methods = reg->wps->config_methods;
     570                 :        388 :         methods &= ~WPS_CONFIG_PUSHBUTTON;
     571                 :            : #ifdef CONFIG_WPS2
     572                 :        388 :         methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON |
     573                 :            :                      WPS_CONFIG_PHY_PUSHBUTTON);
     574                 :            : #endif /* CONFIG_WPS2 */
     575         [ +  + ]:        388 :         if (reg->pbc)
     576                 :         40 :                 wps_set_pushbutton(&methods, reg->wps->config_methods);
     577         [ +  - ]:        388 :         if (reg->sel_reg_config_methods_override >= 0)
     578                 :        388 :                 methods = reg->sel_reg_config_methods_override;
     579                 :        388 :         wpa_printf(MSG_DEBUG, "WPS:  * Selected Registrar Config Methods (%x)",
     580                 :            :                    methods);
     581                 :        388 :         wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR_CONFIG_METHODS);
     582                 :        388 :         wpabuf_put_be16(msg, 2);
     583                 :        388 :         wpabuf_put_be16(msg, methods);
     584                 :        978 :         return 0;
     585                 :            : }
     586                 :            : 
     587                 :            : 
     588                 :        489 : static int wps_build_probe_config_methods(struct wps_registrar *reg,
     589                 :            :                                           struct wpabuf *msg)
     590                 :            : {
     591                 :            :         u16 methods;
     592                 :            :         /*
     593                 :            :          * These are the methods that the AP supports as an Enrollee for adding
     594                 :            :          * external Registrars.
     595                 :            :          */
     596                 :        489 :         methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON;
     597                 :            : #ifdef CONFIG_WPS2
     598                 :        489 :         methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON |
     599                 :            :                      WPS_CONFIG_PHY_PUSHBUTTON);
     600                 :            : #endif /* CONFIG_WPS2 */
     601                 :        489 :         wpa_printf(MSG_DEBUG, "WPS:  * Config Methods (%x)", methods);
     602                 :        489 :         wpabuf_put_be16(msg, ATTR_CONFIG_METHODS);
     603                 :        489 :         wpabuf_put_be16(msg, 2);
     604                 :        489 :         wpabuf_put_be16(msg, methods);
     605                 :        489 :         return 0;
     606                 :            : }
     607                 :            : 
     608                 :            : 
     609                 :        154 : static int wps_build_config_methods_r(struct wps_registrar *reg,
     610                 :            :                                       struct wpabuf *msg)
     611                 :            : {
     612                 :        154 :         return wps_build_config_methods(msg, reg->wps->config_methods);
     613                 :            : }
     614                 :            : 
     615                 :            : 
     616                 :        515 : const u8 * wps_authorized_macs(struct wps_registrar *reg, size_t *count)
     617                 :            : {
     618                 :        515 :         *count = 0;
     619                 :            : 
     620                 :            : #ifdef CONFIG_WPS2
     621         [ +  - ]:        667 :         while (*count < WPS_MAX_AUTHORIZED_MACS) {
     622         [ +  + ]:        667 :                 if (is_zero_ether_addr(reg->authorized_macs_union[*count]))
     623                 :        515 :                         break;
     624                 :        152 :                 (*count)++;
     625                 :            :         }
     626                 :            : #endif /* CONFIG_WPS2 */
     627                 :            : 
     628                 :        515 :         return (const u8 *) reg->authorized_macs_union;
     629                 :            : }
     630                 :            : 
     631                 :            : 
     632                 :            : /**
     633                 :            :  * wps_registrar_init - Initialize WPS Registrar data
     634                 :            :  * @wps: Pointer to longterm WPS context
     635                 :            :  * @cfg: Registrar configuration
     636                 :            :  * Returns: Pointer to allocated Registrar data or %NULL on failure
     637                 :            :  *
     638                 :            :  * This function is used to initialize WPS Registrar functionality. It can be
     639                 :            :  * used for a single Registrar run (e.g., when run in a supplicant) or multiple
     640                 :            :  * runs (e.g., when run as an internal Registrar in an AP). Caller is
     641                 :            :  * responsible for freeing the returned data with wps_registrar_deinit() when
     642                 :            :  * Registrar functionality is not needed anymore.
     643                 :            :  */
     644                 :            : struct wps_registrar *
     645                 :        175 : wps_registrar_init(struct wps_context *wps,
     646                 :            :                    const struct wps_registrar_config *cfg)
     647                 :            : {
     648                 :        175 :         struct wps_registrar *reg = os_zalloc(sizeof(*reg));
     649         [ -  + ]:        175 :         if (reg == NULL)
     650                 :          0 :                 return NULL;
     651                 :            : 
     652                 :        175 :         dl_list_init(&reg->pins);
     653                 :        175 :         dl_list_init(&reg->nfc_pw_tokens);
     654                 :        175 :         reg->wps = wps;
     655                 :        175 :         reg->new_psk_cb = cfg->new_psk_cb;
     656                 :        175 :         reg->set_ie_cb = cfg->set_ie_cb;
     657                 :        175 :         reg->pin_needed_cb = cfg->pin_needed_cb;
     658                 :        175 :         reg->reg_success_cb = cfg->reg_success_cb;
     659                 :        175 :         reg->set_sel_reg_cb = cfg->set_sel_reg_cb;
     660                 :        175 :         reg->enrollee_seen_cb = cfg->enrollee_seen_cb;
     661                 :        175 :         reg->cb_ctx = cfg->cb_ctx;
     662                 :        175 :         reg->skip_cred_build = cfg->skip_cred_build;
     663         [ -  + ]:        175 :         if (cfg->extra_cred) {
     664                 :          0 :                 reg->extra_cred = wpabuf_alloc_copy(cfg->extra_cred,
     665                 :            :                                                     cfg->extra_cred_len);
     666         [ #  # ]:          0 :                 if (reg->extra_cred == NULL) {
     667                 :          0 :                         os_free(reg);
     668                 :          0 :                         return NULL;
     669                 :            :                 }
     670                 :            :         }
     671                 :        175 :         reg->disable_auto_conf = cfg->disable_auto_conf;
     672                 :        175 :         reg->sel_reg_dev_password_id_override = -1;
     673                 :        175 :         reg->sel_reg_config_methods_override = -1;
     674                 :        175 :         reg->static_wep_only = cfg->static_wep_only;
     675                 :        175 :         reg->dualband = cfg->dualband;
     676                 :        175 :         reg->force_per_enrollee_psk = cfg->force_per_enrollee_psk;
     677                 :            : 
     678         [ -  + ]:        175 :         if (wps_set_ie(reg)) {
     679                 :          0 :                 wps_registrar_deinit(reg);
     680                 :          0 :                 return NULL;
     681                 :            :         }
     682                 :            : 
     683                 :        175 :         return reg;
     684                 :            : }
     685                 :            : 
     686                 :            : 
     687                 :            : /**
     688                 :            :  * wps_registrar_deinit - Deinitialize WPS Registrar data
     689                 :            :  * @reg: Registrar data from wps_registrar_init()
     690                 :            :  */
     691                 :        175 : void wps_registrar_deinit(struct wps_registrar *reg)
     692                 :            : {
     693         [ -  + ]:        175 :         if (reg == NULL)
     694                 :        175 :                 return;
     695                 :        175 :         eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL);
     696                 :        175 :         eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
     697                 :        175 :         wps_free_pins(&reg->pins);
     698                 :        175 :         wps_free_nfc_pw_tokens(&reg->nfc_pw_tokens, 0);
     699                 :        175 :         wps_free_pbc_sessions(reg->pbc_sessions);
     700                 :        175 :         wpabuf_free(reg->extra_cred);
     701                 :        175 :         wps_free_devices(reg->devices);
     702                 :        175 :         os_free(reg);
     703                 :            : }
     704                 :            : 
     705                 :            : 
     706                 :        101 : static void wps_registrar_invalidate_unused(struct wps_registrar *reg)
     707                 :            : {
     708                 :            :         struct wps_uuid_pin *pin;
     709                 :            : 
     710         [ +  + ]:        129 :         dl_list_for_each(pin, &reg->pins, struct wps_uuid_pin, list) {
     711 [ +  + ][ +  - ]:         29 :                 if (pin->wildcard_uuid == 1 && !(pin->flags & PIN_LOCKED)) {
     712                 :          1 :                         wpa_printf(MSG_DEBUG, "WPS: Invalidate previously "
     713                 :            :                                    "configured wildcard PIN");
     714                 :          1 :                         wps_registrar_remove_pin(reg, pin);
     715                 :          1 :                         break;
     716                 :            :                 }
     717                 :            :         }
     718                 :        101 : }
     719                 :            : 
     720                 :            : 
     721                 :            : /**
     722                 :            :  * wps_registrar_add_pin - Configure a new PIN for Registrar
     723                 :            :  * @reg: Registrar data from wps_registrar_init()
     724                 :            :  * @addr: Enrollee MAC address or %NULL if not known
     725                 :            :  * @uuid: UUID-E or %NULL for wildcard (any UUID)
     726                 :            :  * @pin: PIN (Device Password)
     727                 :            :  * @pin_len: Length of pin in octets
     728                 :            :  * @timeout: Time (in seconds) when the PIN will be invalidated; 0 = no timeout
     729                 :            :  * Returns: 0 on success, -1 on failure
     730                 :            :  */
     731                 :        106 : int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *addr,
     732                 :            :                           const u8 *uuid, const u8 *pin, size_t pin_len,
     733                 :            :                           int timeout)
     734                 :            : {
     735                 :            :         struct wps_uuid_pin *p;
     736                 :            : 
     737                 :        106 :         p = os_zalloc(sizeof(*p));
     738         [ -  + ]:        106 :         if (p == NULL)
     739                 :          0 :                 return -1;
     740         [ +  + ]:        106 :         if (addr)
     741                 :         40 :                 os_memcpy(p->enrollee_addr, addr, ETH_ALEN);
     742         [ +  + ]:        106 :         if (uuid == NULL)
     743                 :        101 :                 p->wildcard_uuid = 1;
     744                 :            :         else
     745                 :          5 :                 os_memcpy(p->uuid, uuid, WPS_UUID_LEN);
     746                 :        106 :         p->pin = os_malloc(pin_len);
     747         [ -  + ]:        106 :         if (p->pin == NULL) {
     748                 :          0 :                 os_free(p);
     749                 :          0 :                 return -1;
     750                 :            :         }
     751                 :        106 :         os_memcpy(p->pin, pin, pin_len);
     752                 :        106 :         p->pin_len = pin_len;
     753                 :            : 
     754         [ +  + ]:        106 :         if (timeout) {
     755                 :          4 :                 p->flags |= PIN_EXPIRES;
     756                 :          4 :                 os_get_reltime(&p->expiration);
     757                 :          4 :                 p->expiration.sec += timeout;
     758                 :            :         }
     759                 :            : 
     760         [ +  + ]:        106 :         if (p->wildcard_uuid)
     761                 :        101 :                 wps_registrar_invalidate_unused(reg);
     762                 :            : 
     763                 :        106 :         dl_list_add(&reg->pins, &p->list);
     764                 :            : 
     765                 :        106 :         wpa_printf(MSG_DEBUG, "WPS: A new PIN configured (timeout=%d)",
     766                 :            :                    timeout);
     767                 :        106 :         wpa_hexdump(MSG_DEBUG, "WPS: UUID", uuid, WPS_UUID_LEN);
     768                 :        106 :         wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: PIN", pin, pin_len);
     769                 :        106 :         reg->selected_registrar = 1;
     770                 :        106 :         reg->pbc = 0;
     771         [ +  + ]:        106 :         if (addr)
     772                 :         40 :                 wps_registrar_add_authorized_mac(reg, addr);
     773                 :            :         else
     774                 :         66 :                 wps_registrar_add_authorized_mac(
     775                 :            :                         reg, (u8 *) "\xff\xff\xff\xff\xff\xff");
     776                 :        106 :         wps_registrar_selected_registrar_changed(reg, 0);
     777                 :        106 :         eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
     778                 :        106 :         eloop_register_timeout(WPS_PBC_WALK_TIME, 0,
     779                 :            :                                wps_registrar_set_selected_timeout,
     780                 :            :                                reg, NULL);
     781                 :            : 
     782                 :        106 :         return 0;
     783                 :            : }
     784                 :            : 
     785                 :            : 
     786                 :         94 : static void wps_registrar_remove_pin(struct wps_registrar *reg,
     787                 :            :                                      struct wps_uuid_pin *pin)
     788                 :            : {
     789                 :            :         u8 *addr;
     790                 :         94 :         u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
     791                 :            : 
     792         [ +  + ]:         94 :         if (is_zero_ether_addr(pin->enrollee_addr))
     793                 :         55 :                 addr = bcast;
     794                 :            :         else
     795                 :         39 :                 addr = pin->enrollee_addr;
     796                 :         94 :         wps_registrar_remove_authorized_mac(reg, addr);
     797                 :         94 :         wps_remove_pin(pin);
     798                 :         94 :         wps_registrar_selected_registrar_changed(reg, 0);
     799                 :         94 : }
     800                 :            : 
     801                 :            : 
     802                 :        111 : static void wps_registrar_expire_pins(struct wps_registrar *reg)
     803                 :            : {
     804                 :            :         struct wps_uuid_pin *pin, *prev;
     805                 :            :         struct os_reltime now;
     806                 :            : 
     807                 :        111 :         os_get_reltime(&now);
     808         [ +  + ]:        244 :         dl_list_for_each_safe(pin, prev, &reg->pins, struct wps_uuid_pin, list)
     809                 :            :         {
     810   [ +  +  -  + ]:        136 :                 if ((pin->flags & PIN_EXPIRES) &&
     811                 :          3 :                     os_reltime_before(&pin->expiration, &now)) {
     812                 :          0 :                         wpa_hexdump(MSG_DEBUG, "WPS: Expired PIN for UUID",
     813                 :          0 :                                     pin->uuid, WPS_UUID_LEN);
     814                 :          0 :                         wps_registrar_remove_pin(reg, pin);
     815                 :            :                 }
     816                 :            :         }
     817                 :        111 : }
     818                 :            : 
     819                 :            : 
     820                 :            : /**
     821                 :            :  * wps_registrar_invalidate_wildcard_pin - Invalidate a wildcard PIN
     822                 :            :  * @reg: Registrar data from wps_registrar_init()
     823                 :            :  * @dev_pw: PIN to search for or %NULL to match any
     824                 :            :  * @dev_pw_len: Length of dev_pw in octets
     825                 :            :  * Returns: 0 on success, -1 if not wildcard PIN is enabled
     826                 :            :  */
     827                 :          3 : static int wps_registrar_invalidate_wildcard_pin(struct wps_registrar *reg,
     828                 :            :                                                  const u8 *dev_pw,
     829                 :            :                                                  size_t dev_pw_len)
     830                 :            : {
     831                 :            :         struct wps_uuid_pin *pin, *prev;
     832                 :            : 
     833         [ +  + ]:          3 :         dl_list_for_each_safe(pin, prev, &reg->pins, struct wps_uuid_pin, list)
     834                 :            :         {
     835 [ +  + ][ +  - ]:          2 :                 if (dev_pw && pin->pin &&
                 [ +  - ]
     836         [ -  + ]:          1 :                     (dev_pw_len != pin->pin_len ||
     837                 :          1 :                      os_memcmp(dev_pw, pin->pin, dev_pw_len) != 0))
     838                 :          0 :                         continue; /* different PIN */
     839         [ +  - ]:          2 :                 if (pin->wildcard_uuid) {
     840                 :          2 :                         wpa_hexdump(MSG_DEBUG, "WPS: Invalidated PIN for UUID",
     841                 :          2 :                                     pin->uuid, WPS_UUID_LEN);
     842                 :          2 :                         wps_registrar_remove_pin(reg, pin);
     843                 :          2 :                         return 0;
     844                 :            :                 }
     845                 :            :         }
     846                 :            : 
     847                 :          3 :         return -1;
     848                 :            : }
     849                 :            : 
     850                 :            : 
     851                 :            : /**
     852                 :            :  * wps_registrar_invalidate_pin - Invalidate a PIN for a specific UUID-E
     853                 :            :  * @reg: Registrar data from wps_registrar_init()
     854                 :            :  * @uuid: UUID-E
     855                 :            :  * Returns: 0 on success, -1 on failure (e.g., PIN not found)
     856                 :            :  */
     857                 :        116 : int wps_registrar_invalidate_pin(struct wps_registrar *reg, const u8 *uuid)
     858                 :            : {
     859                 :            :         struct wps_uuid_pin *pin, *prev;
     860                 :            : 
     861         [ +  + ]:        117 :         dl_list_for_each_safe(pin, prev, &reg->pins, struct wps_uuid_pin, list)
     862                 :            :         {
     863         [ +  + ]:         92 :                 if (os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) {
     864                 :         91 :                         wpa_hexdump(MSG_DEBUG, "WPS: Invalidated PIN for UUID",
     865                 :         91 :                                     pin->uuid, WPS_UUID_LEN);
     866                 :         91 :                         wps_registrar_remove_pin(reg, pin);
     867                 :         91 :                         return 0;
     868                 :            :                 }
     869                 :            :         }
     870                 :            : 
     871                 :        116 :         return -1;
     872                 :            : }
     873                 :            : 
     874                 :            : 
     875                 :        111 : static const u8 * wps_registrar_get_pin(struct wps_registrar *reg,
     876                 :            :                                         const u8 *uuid, size_t *pin_len)
     877                 :            : {
     878                 :        111 :         struct wps_uuid_pin *pin, *found = NULL;
     879                 :            : 
     880                 :        111 :         wps_registrar_expire_pins(reg);
     881                 :            : 
     882         [ +  + ]:        238 :         dl_list_for_each(pin, &reg->pins, struct wps_uuid_pin, list) {
     883 [ +  + ][ +  + ]:        132 :                 if (!pin->wildcard_uuid &&
     884                 :          6 :                     os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) {
     885                 :          5 :                         found = pin;
     886                 :          5 :                         break;
     887                 :            :                 }
     888                 :            :         }
     889                 :            : 
     890         [ +  + ]:        111 :         if (!found) {
     891                 :            :                 /* Check for wildcard UUIDs since none of the UUID-specific
     892                 :            :                  * PINs matched */
     893         [ +  + ]:        106 :                 dl_list_for_each(pin, &reg->pins, struct wps_uuid_pin, list) {
     894 [ -  + ][ #  # ]:         98 :                         if (pin->wildcard_uuid == 1 ||
     895                 :          0 :                             pin->wildcard_uuid == 2) {
     896                 :         98 :                                 wpa_printf(MSG_DEBUG, "WPS: Found a wildcard "
     897                 :            :                                            "PIN. Assigned it for this UUID-E");
     898                 :         98 :                                 pin->wildcard_uuid++;
     899                 :         98 :                                 os_memcpy(pin->uuid, uuid, WPS_UUID_LEN);
     900                 :         98 :                                 found = pin;
     901                 :         98 :                                 break;
     902                 :            :                         }
     903                 :            :                 }
     904                 :            :         }
     905                 :            : 
     906         [ +  + ]:        111 :         if (!found)
     907                 :          8 :                 return NULL;
     908                 :            : 
     909                 :            :         /*
     910                 :            :          * Lock the PIN to avoid attacks based on concurrent re-use of the PIN
     911                 :            :          * that could otherwise avoid PIN invalidations.
     912                 :            :          */
     913         [ -  + ]:        103 :         if (found->flags & PIN_LOCKED) {
     914                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Selected PIN locked - do not "
     915                 :            :                            "allow concurrent re-use");
     916                 :          0 :                 return NULL;
     917                 :            :         }
     918                 :        103 :         *pin_len = found->pin_len;
     919                 :        103 :         found->flags |= PIN_LOCKED;
     920                 :        111 :         return found->pin;
     921                 :            : }
     922                 :            : 
     923                 :            : 
     924                 :            : /**
     925                 :            :  * wps_registrar_unlock_pin - Unlock a PIN for a specific UUID-E
     926                 :            :  * @reg: Registrar data from wps_registrar_init()
     927                 :            :  * @uuid: UUID-E
     928                 :            :  * Returns: 0 on success, -1 on failure
     929                 :            :  *
     930                 :            :  * PINs are locked to enforce only one concurrent use. This function unlocks a
     931                 :            :  * PIN to allow it to be used again. If the specified PIN was configured using
     932                 :            :  * a wildcard UUID, it will be removed instead of allowing multiple uses.
     933                 :            :  */
     934                 :        264 : int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid)
     935                 :            : {
     936                 :            :         struct wps_uuid_pin *pin;
     937                 :            : 
     938         [ +  + ]:        270 :         dl_list_for_each(pin, &reg->pins, struct wps_uuid_pin, list) {
     939         [ +  + ]:        108 :                 if (os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) {
     940         [ -  + ]:        102 :                         if (pin->wildcard_uuid == 3) {
     941                 :          0 :                                 wpa_printf(MSG_DEBUG, "WPS: Invalidating used "
     942                 :            :                                            "wildcard PIN");
     943                 :          0 :                                 return wps_registrar_invalidate_pin(reg, uuid);
     944                 :            :                         }
     945                 :        102 :                         pin->flags &= ~PIN_LOCKED;
     946                 :        102 :                         return 0;
     947                 :            :                 }
     948                 :            :         }
     949                 :            : 
     950                 :        264 :         return -1;
     951                 :            : }
     952                 :            : 
     953                 :            : 
     954                 :         19 : static void wps_registrar_stop_pbc(struct wps_registrar *reg)
     955                 :            : {
     956                 :         19 :         reg->selected_registrar = 0;
     957                 :         19 :         reg->pbc = 0;
     958                 :         19 :         os_memset(reg->p2p_dev_addr, 0, ETH_ALEN);
     959                 :         19 :         wps_registrar_remove_authorized_mac(reg,
     960                 :            :                                             (u8 *) "\xff\xff\xff\xff\xff\xff");
     961                 :         19 :         wps_registrar_selected_registrar_changed(reg, 0);
     962                 :         19 : }
     963                 :            : 
     964                 :            : 
     965                 :          3 : static void wps_registrar_pbc_timeout(void *eloop_ctx, void *timeout_ctx)
     966                 :            : {
     967                 :          3 :         struct wps_registrar *reg = eloop_ctx;
     968                 :            : 
     969                 :          3 :         wpa_printf(MSG_DEBUG, "WPS: PBC timed out - disable PBC mode");
     970                 :          3 :         wps_pbc_timeout_event(reg->wps);
     971                 :          3 :         wps_registrar_stop_pbc(reg);
     972                 :          3 : }
     973                 :            : 
     974                 :            : 
     975                 :            : /**
     976                 :            :  * wps_registrar_button_pushed - Notify Registrar that AP button was pushed
     977                 :            :  * @reg: Registrar data from wps_registrar_init()
     978                 :            :  * @p2p_dev_addr: Limit allowed PBC devices to the specified P2P device, %NULL
     979                 :            :  *      indicates no such filtering
     980                 :            :  * Returns: 0 on success, -1 on failure, -2 on session overlap
     981                 :            :  *
     982                 :            :  * This function is called on an AP when a push button is pushed to activate
     983                 :            :  * PBC mode. The PBC mode will be stopped after walk time (2 minutes) timeout
     984                 :            :  * or when a PBC registration is completed. If more than one Enrollee in active
     985                 :            :  * PBC mode has been detected during the monitor time (previous 2 minutes), the
     986                 :            :  * PBC mode is not activated and -2 is returned to indicate session overlap.
     987                 :            :  * This is skipped if a specific Enrollee is selected.
     988                 :            :  */
     989                 :         22 : int wps_registrar_button_pushed(struct wps_registrar *reg,
     990                 :            :                                 const u8 *p2p_dev_addr)
     991                 :            : {
     992   [ +  +  +  + ]:         41 :         if (p2p_dev_addr == NULL &&
     993                 :         19 :             wps_registrar_pbc_overlap(reg, NULL, NULL)) {
     994                 :          1 :                 wpa_printf(MSG_DEBUG, "WPS: PBC overlap - do not start PBC "
     995                 :            :                            "mode");
     996                 :          1 :                 wps_pbc_overlap_event(reg->wps);
     997                 :          1 :                 return -2;
     998                 :            :         }
     999                 :         21 :         wpa_printf(MSG_DEBUG, "WPS: Button pushed - PBC mode started");
    1000                 :         21 :         reg->force_pbc_overlap = 0;
    1001                 :         21 :         reg->selected_registrar = 1;
    1002                 :         21 :         reg->pbc = 1;
    1003         [ +  + ]:         21 :         if (p2p_dev_addr)
    1004                 :          3 :                 os_memcpy(reg->p2p_dev_addr, p2p_dev_addr, ETH_ALEN);
    1005                 :            :         else
    1006                 :         18 :                 os_memset(reg->p2p_dev_addr, 0, ETH_ALEN);
    1007                 :         21 :         wps_registrar_add_authorized_mac(reg,
    1008                 :            :                                          (u8 *) "\xff\xff\xff\xff\xff\xff");
    1009                 :         21 :         wps_registrar_selected_registrar_changed(reg, 0);
    1010                 :            : 
    1011                 :         21 :         wps_pbc_active_event(reg->wps);
    1012                 :         21 :         eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
    1013                 :         21 :         eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL);
    1014                 :         21 :         eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wps_registrar_pbc_timeout,
    1015                 :            :                                reg, NULL);
    1016                 :         22 :         return 0;
    1017                 :            : }
    1018                 :            : 
    1019                 :            : 
    1020                 :         16 : static void wps_registrar_pbc_completed(struct wps_registrar *reg)
    1021                 :            : {
    1022                 :         16 :         wpa_printf(MSG_DEBUG, "WPS: PBC completed - stopping PBC mode");
    1023                 :         16 :         eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL);
    1024                 :         16 :         wps_registrar_stop_pbc(reg);
    1025                 :         16 :         wps_pbc_disable_event(reg->wps);
    1026                 :         16 : }
    1027                 :            : 
    1028                 :            : 
    1029                 :        110 : static void wps_registrar_pin_completed(struct wps_registrar *reg)
    1030                 :            : {
    1031                 :        110 :         wpa_printf(MSG_DEBUG, "WPS: PIN completed using internal Registrar");
    1032                 :        110 :         eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
    1033                 :        110 :         reg->selected_registrar = 0;
    1034                 :        110 :         wps_registrar_selected_registrar_changed(reg, 0);
    1035                 :        110 : }
    1036                 :            : 
    1037                 :            : 
    1038                 :          2 : void wps_registrar_complete(struct wps_registrar *registrar, const u8 *uuid_e,
    1039                 :            :                             const u8 *dev_pw, size_t dev_pw_len)
    1040                 :            : {
    1041         [ +  + ]:          2 :         if (registrar->pbc) {
    1042                 :          1 :                 wps_registrar_remove_pbc_session(registrar,
    1043                 :            :                                                  uuid_e, NULL);
    1044                 :          1 :                 wps_registrar_pbc_completed(registrar);
    1045                 :            : #ifdef WPS_WORKAROUNDS
    1046                 :          1 :                 os_get_reltime(&registrar->pbc_ignore_start);
    1047                 :            : #endif /* WPS_WORKAROUNDS */
    1048                 :          1 :                 os_memcpy(registrar->pbc_ignore_uuid, uuid_e, WPS_UUID_LEN);
    1049                 :            :         } else {
    1050                 :          1 :                 wps_registrar_pin_completed(registrar);
    1051                 :            :         }
    1052                 :            : 
    1053   [ +  -  +  + ]:          4 :         if (dev_pw &&
    1054                 :          2 :             wps_registrar_invalidate_wildcard_pin(registrar, dev_pw,
    1055                 :            :                                                   dev_pw_len) == 0) {
    1056                 :          1 :                 wpa_hexdump_key(MSG_DEBUG, "WPS: Invalidated wildcard PIN",
    1057                 :            :                                 dev_pw, dev_pw_len);
    1058                 :            :         }
    1059                 :          2 : }
    1060                 :            : 
    1061                 :            : 
    1062                 :          8 : int wps_registrar_wps_cancel(struct wps_registrar *reg)
    1063                 :            : {
    1064         [ +  + ]:          8 :         if (reg->pbc) {
    1065                 :          3 :                 wpa_printf(MSG_DEBUG, "WPS: PBC is set - cancelling it");
    1066                 :          3 :                 wps_registrar_pbc_timeout(reg, NULL);
    1067                 :          3 :                 eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL);
    1068                 :          3 :                 return 1;
    1069         [ +  + ]:          5 :         } else if (reg->selected_registrar) {
    1070                 :            :                 /* PIN Method */
    1071                 :          1 :                 wpa_printf(MSG_DEBUG, "WPS: PIN is set - cancelling it");
    1072                 :          1 :                 wps_registrar_pin_completed(reg);
    1073                 :          1 :                 wps_registrar_invalidate_wildcard_pin(reg, NULL, 0);
    1074                 :          1 :                 return 1;
    1075                 :            :         }
    1076                 :          8 :         return 0;
    1077                 :            : }
    1078                 :            : 
    1079                 :            : 
    1080                 :            : /**
    1081                 :            :  * wps_registrar_probe_req_rx - Notify Registrar of Probe Request
    1082                 :            :  * @reg: Registrar data from wps_registrar_init()
    1083                 :            :  * @addr: MAC address of the Probe Request sender
    1084                 :            :  * @wps_data: WPS IE contents
    1085                 :            :  *
    1086                 :            :  * This function is called on an AP when a Probe Request with WPS IE is
    1087                 :            :  * received. This is used to track PBC mode use and to detect possible overlap
    1088                 :            :  * situation with other WPS APs.
    1089                 :            :  */
    1090                 :        254 : void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr,
    1091                 :            :                                 const struct wpabuf *wps_data,
    1092                 :            :                                 int p2p_wildcard)
    1093                 :            : {
    1094                 :            :         struct wps_parse_attr attr;
    1095                 :        254 :         int skip_add = 0;
    1096                 :            : 
    1097                 :        254 :         wpa_hexdump_buf(MSG_MSGDUMP,
    1098                 :            :                         "WPS: Probe Request with WPS data received",
    1099                 :            :                         wps_data);
    1100                 :            : 
    1101         [ -  + ]:        254 :         if (wps_parse_msg(wps_data, &attr) < 0)
    1102                 :          0 :                 return;
    1103                 :            : 
    1104         [ -  + ]:        254 :         if (attr.config_methods == NULL) {
    1105                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No Config Methods attribute in "
    1106                 :            :                            "Probe Request");
    1107                 :          0 :                 return;
    1108                 :            :         }
    1109                 :            : 
    1110         [ -  + ]:        254 :         if (attr.dev_password_id == NULL) {
    1111                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No Device Password Id attribute "
    1112                 :            :                            "in Probe Request");
    1113                 :          0 :                 return;
    1114                 :            :         }
    1115                 :            : 
    1116 [ +  + ][ +  - ]:        254 :         if (reg->enrollee_seen_cb && attr.uuid_e &&
                 [ +  - ]
    1117 [ +  - ][ +  - ]:        229 :             attr.primary_dev_type && attr.request_type && !p2p_wildcard) {
    1118                 :        229 :                 char *dev_name = NULL;
    1119         [ +  - ]:        229 :                 if (attr.dev_name) {
    1120                 :        229 :                         dev_name = os_zalloc(attr.dev_name_len + 1);
    1121         [ +  - ]:        229 :                         if (dev_name) {
    1122                 :        229 :                                 os_memcpy(dev_name, attr.dev_name,
    1123                 :            :                                           attr.dev_name_len);
    1124                 :            :                         }
    1125                 :            :                 }
    1126                 :        229 :                 reg->enrollee_seen_cb(reg->cb_ctx, addr, attr.uuid_e,
    1127                 :            :                                       attr.primary_dev_type,
    1128                 :        229 :                                       WPA_GET_BE16(attr.config_methods),
    1129                 :        229 :                                       WPA_GET_BE16(attr.dev_password_id),
    1130                 :        229 :                                       *attr.request_type, dev_name);
    1131                 :        229 :                 os_free(dev_name);
    1132                 :            :         }
    1133                 :            : 
    1134         [ +  + ]:        254 :         if (WPA_GET_BE16(attr.dev_password_id) != DEV_PW_PUSHBUTTON)
    1135                 :        231 :                 return; /* Not PBC */
    1136                 :            : 
    1137                 :         23 :         wpa_printf(MSG_DEBUG, "WPS: Probe Request for PBC received from "
    1138                 :        138 :                    MACSTR, MAC2STR(addr));
    1139         [ -  + ]:         23 :         if (attr.uuid_e == NULL) {
    1140                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Invalid Probe Request WPS IE: No "
    1141                 :            :                            "UUID-E included");
    1142                 :          0 :                 return;
    1143                 :            :         }
    1144                 :         23 :         wpa_hexdump(MSG_DEBUG, "WPS: UUID-E from Probe Request", attr.uuid_e,
    1145                 :            :                     WPS_UUID_LEN);
    1146                 :            : 
    1147                 :            : #ifdef WPS_WORKAROUNDS
    1148 [ #  # ][ -  + ]:         23 :         if (reg->pbc_ignore_start.sec &&
    1149                 :          0 :             os_memcmp(attr.uuid_e, reg->pbc_ignore_uuid, WPS_UUID_LEN) == 0) {
    1150                 :            :                 struct os_reltime now, dur;
    1151                 :          0 :                 os_get_reltime(&now);
    1152                 :          0 :                 os_reltime_sub(&now, &reg->pbc_ignore_start, &dur);
    1153 [ #  # ][ #  # ]:          0 :                 if (dur.sec >= 0 && dur.sec < 5) {
    1154                 :          0 :                         wpa_printf(MSG_DEBUG, "WPS: Ignore PBC activation "
    1155                 :            :                                    "based on Probe Request from the Enrollee "
    1156                 :            :                                    "that just completed PBC provisioning");
    1157                 :          0 :                         skip_add = 1;
    1158                 :            :                 } else
    1159                 :          0 :                         reg->pbc_ignore_start.sec = 0;
    1160                 :            :         }
    1161                 :            : #endif /* WPS_WORKAROUNDS */
    1162                 :            : 
    1163         [ +  - ]:         23 :         if (!skip_add)
    1164                 :         23 :                 wps_registrar_add_pbc_session(reg, addr, attr.uuid_e);
    1165         [ +  + ]:         23 :         if (wps_registrar_pbc_overlap(reg, addr, attr.uuid_e)) {
    1166                 :          1 :                 wpa_printf(MSG_DEBUG, "WPS: PBC session overlap detected");
    1167                 :          1 :                 reg->force_pbc_overlap = 1;
    1168                 :        254 :                 wps_pbc_overlap_event(reg->wps);
    1169                 :            :         }
    1170                 :            : }
    1171                 :            : 
    1172                 :            : 
    1173                 :          8 : static int wps_cb_new_psk(struct wps_registrar *reg, const u8 *mac_addr,
    1174                 :            :                           const u8 *p2p_dev_addr, const u8 *psk, size_t psk_len)
    1175                 :            : {
    1176         [ -  + ]:          8 :         if (reg->new_psk_cb == NULL)
    1177                 :          0 :                 return 0;
    1178                 :            : 
    1179                 :          8 :         return reg->new_psk_cb(reg->cb_ctx, mac_addr, p2p_dev_addr, psk,
    1180                 :            :                                psk_len);
    1181                 :            : }
    1182                 :            : 
    1183                 :            : 
    1184                 :          8 : static void wps_cb_pin_needed(struct wps_registrar *reg, const u8 *uuid_e,
    1185                 :            :                               const struct wps_device_data *dev)
    1186                 :            : {
    1187         [ -  + ]:          8 :         if (reg->pin_needed_cb == NULL)
    1188                 :          8 :                 return;
    1189                 :            : 
    1190                 :          8 :         reg->pin_needed_cb(reg->cb_ctx, uuid_e, dev);
    1191                 :            : }
    1192                 :            : 
    1193                 :            : 
    1194                 :        111 : static void wps_cb_reg_success(struct wps_registrar *reg, const u8 *mac_addr,
    1195                 :            :                                const u8 *uuid_e, const u8 *dev_pw,
    1196                 :            :                                size_t dev_pw_len)
    1197                 :            : {
    1198         [ +  + ]:        111 :         if (reg->reg_success_cb == NULL)
    1199                 :        111 :                 return;
    1200                 :            : 
    1201                 :        100 :         reg->reg_success_cb(reg->cb_ctx, mac_addr, uuid_e, dev_pw, dev_pw_len);
    1202                 :            : }
    1203                 :            : 
    1204                 :            : 
    1205                 :        489 : static int wps_cb_set_ie(struct wps_registrar *reg, struct wpabuf *beacon_ie,
    1206                 :            :                          struct wpabuf *probe_resp_ie)
    1207                 :            : {
    1208                 :        489 :         return reg->set_ie_cb(reg->cb_ctx, beacon_ie, probe_resp_ie);
    1209                 :            : }
    1210                 :            : 
    1211                 :            : 
    1212                 :        428 : static void wps_cb_set_sel_reg(struct wps_registrar *reg)
    1213                 :            : {
    1214                 :        428 :         u16 methods = 0;
    1215         [ +  + ]:        428 :         if (reg->set_sel_reg_cb == NULL)
    1216                 :        428 :                 return;
    1217                 :            : 
    1218         [ +  + ]:         93 :         if (reg->selected_registrar) {
    1219                 :         64 :                 methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON;
    1220                 :            : #ifdef CONFIG_WPS2
    1221                 :         64 :                 methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON |
    1222                 :            :                              WPS_CONFIG_PHY_PUSHBUTTON);
    1223                 :            : #endif /* CONFIG_WPS2 */
    1224         [ +  + ]:         64 :                 if (reg->pbc)
    1225                 :          1 :                         wps_set_pushbutton(&methods, reg->wps->config_methods);
    1226                 :            :         }
    1227                 :            : 
    1228                 :         93 :         wpa_printf(MSG_DEBUG, "WPS: wps_cb_set_sel_reg: sel_reg=%d "
    1229                 :            :                    "config_methods=0x%x pbc=%d methods=0x%x",
    1230                 :         93 :                    reg->selected_registrar, reg->wps->config_methods,
    1231                 :            :                    reg->pbc, methods);
    1232                 :            : 
    1233         [ +  + ]:         93 :         reg->set_sel_reg_cb(reg->cb_ctx, reg->selected_registrar,
    1234                 :         93 :                             reg->pbc ? DEV_PW_PUSHBUTTON : DEV_PW_DEFAULT,
    1235                 :            :                             methods);
    1236                 :            : }
    1237                 :            : 
    1238                 :            : 
    1239                 :        621 : static int wps_set_ie(struct wps_registrar *reg)
    1240                 :            : {
    1241                 :            :         struct wpabuf *beacon;
    1242                 :            :         struct wpabuf *probe;
    1243                 :            :         const u8 *auth_macs;
    1244                 :            :         size_t count;
    1245                 :        621 :         size_t vendor_len = 0;
    1246                 :            :         int i;
    1247                 :            : 
    1248         [ +  + ]:        621 :         if (reg->set_ie_cb == NULL)
    1249                 :        132 :                 return 0;
    1250                 :            : 
    1251         [ +  + ]:       5379 :         for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
    1252         [ -  + ]:       4890 :                 if (reg->wps->dev.vendor_ext[i]) {
    1253                 :          0 :                         vendor_len += 2 + 2;
    1254                 :          0 :                         vendor_len += wpabuf_len(reg->wps->dev.vendor_ext[i]);
    1255                 :            :                 }
    1256                 :            :         }
    1257                 :            : 
    1258                 :        489 :         beacon = wpabuf_alloc(400 + vendor_len);
    1259         [ -  + ]:        489 :         if (beacon == NULL)
    1260                 :          0 :                 return -1;
    1261                 :        489 :         probe = wpabuf_alloc(500 + vendor_len);
    1262         [ -  + ]:        489 :         if (probe == NULL) {
    1263                 :          0 :                 wpabuf_free(beacon);
    1264                 :          0 :                 return -1;
    1265                 :            :         }
    1266                 :            : 
    1267                 :        489 :         auth_macs = wps_authorized_macs(reg, &count);
    1268                 :            : 
    1269                 :        489 :         wpa_printf(MSG_DEBUG, "WPS: Build Beacon IEs");
    1270                 :            : 
    1271   [ +  -  +  - ]:        978 :         if (wps_build_version(beacon) ||
    1272         [ +  - ]:        978 :             wps_build_wps_state(reg->wps, beacon) ||
    1273         [ +  - ]:        978 :             wps_build_ap_setup_locked(reg->wps, beacon) ||
    1274         [ +  - ]:        978 :             wps_build_selected_registrar(reg, beacon) ||
    1275         [ +  - ]:        978 :             wps_build_sel_reg_dev_password_id(reg, beacon) ||
    1276         [ +  - ]:        978 :             wps_build_sel_reg_config_methods(reg, beacon) ||
    1277         [ +  + ]:        978 :             wps_build_sel_pbc_reg_uuid_e(reg, beacon) ||
    1278   [ +  -  +  - ]:        500 :             (reg->dualband && wps_build_rf_bands(&reg->wps->dev, beacon, 0)) ||
    1279         [ -  + ]:        978 :             wps_build_wfa_ext(beacon, 0, auth_macs, count) ||
    1280                 :        489 :             wps_build_vendor_ext(&reg->wps->dev, beacon)) {
    1281                 :          0 :                 wpabuf_free(beacon);
    1282                 :          0 :                 wpabuf_free(probe);
    1283                 :          0 :                 return -1;
    1284                 :            :         }
    1285                 :            : 
    1286                 :            : #ifdef CONFIG_P2P
    1287   [ +  -  -  + ]:        646 :         if (wps_build_dev_name(&reg->wps->dev, beacon) ||
    1288                 :        323 :             wps_build_primary_dev_type(&reg->wps->dev, beacon)) {
    1289                 :          0 :                 wpabuf_free(beacon);
    1290                 :          0 :                 wpabuf_free(probe);
    1291                 :          0 :                 return -1;
    1292                 :            :         }
    1293                 :            : #endif /* CONFIG_P2P */
    1294                 :            : 
    1295                 :        489 :         wpa_printf(MSG_DEBUG, "WPS: Build Probe Response IEs");
    1296                 :            : 
    1297   [ +  -  +  - ]:        978 :         if (wps_build_version(probe) ||
    1298         [ +  - ]:        978 :             wps_build_wps_state(reg->wps, probe) ||
    1299         [ +  - ]:        978 :             wps_build_ap_setup_locked(reg->wps, probe) ||
    1300         [ +  - ]:        978 :             wps_build_selected_registrar(reg, probe) ||
    1301         [ +  - ]:        978 :             wps_build_sel_reg_dev_password_id(reg, probe) ||
    1302         [ +  - ]:        978 :             wps_build_sel_reg_config_methods(reg, probe) ||
    1303         [ +  - ]:        489 :             wps_build_resp_type(probe, reg->wps->ap ? WPS_RESP_AP :
    1304         [ +  - ]:        489 :                                 WPS_RESP_REGISTRAR) ||
    1305         [ +  - ]:        978 :             wps_build_uuid_e(probe, reg->wps->uuid) ||
    1306         [ +  - ]:        978 :             wps_build_device_attrs(&reg->wps->dev, probe) ||
    1307         [ +  + ]:        978 :             wps_build_probe_config_methods(reg, probe) ||
    1308   [ +  -  +  - ]:        500 :             (reg->dualband && wps_build_rf_bands(&reg->wps->dev, probe, 0)) ||
    1309         [ -  + ]:        978 :             wps_build_wfa_ext(probe, 0, auth_macs, count) ||
    1310                 :        489 :             wps_build_vendor_ext(&reg->wps->dev, probe)) {
    1311                 :          0 :                 wpabuf_free(beacon);
    1312                 :          0 :                 wpabuf_free(probe);
    1313                 :          0 :                 return -1;
    1314                 :            :         }
    1315                 :            : 
    1316                 :        489 :         beacon = wps_ie_encapsulate(beacon);
    1317                 :        489 :         probe = wps_ie_encapsulate(probe);
    1318                 :            : 
    1319 [ -  + ][ +  - ]:        489 :         if (!beacon || !probe) {
    1320                 :          0 :                 wpabuf_free(beacon);
    1321                 :          0 :                 wpabuf_free(probe);
    1322                 :          0 :                 return -1;
    1323                 :            :         }
    1324                 :            : 
    1325         [ -  + ]:        489 :         if (reg->static_wep_only) {
    1326                 :            :                 /*
    1327                 :            :                  * Windows XP and Vista clients can get confused about
    1328                 :            :                  * EAP-Identity/Request when they probe the network with
    1329                 :            :                  * EAPOL-Start. In such a case, they may assume the network is
    1330                 :            :                  * using IEEE 802.1X and prompt user for a certificate while
    1331                 :            :                  * the correct (non-WPS) behavior would be to ask for the
    1332                 :            :                  * static WEP key. As a workaround, use Microsoft Provisioning
    1333                 :            :                  * IE to advertise that legacy 802.1X is not supported.
    1334                 :            :                  */
    1335                 :          0 :                 const u8 ms_wps[7] = {
    1336                 :            :                         WLAN_EID_VENDOR_SPECIFIC, 5,
    1337                 :            :                         /* Microsoft Provisioning IE (00:50:f2:5) */
    1338                 :            :                         0x00, 0x50, 0xf2, 5,
    1339                 :            :                         0x00 /* no legacy 802.1X or MS WPS */
    1340                 :            :                 };
    1341                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Add Microsoft Provisioning IE "
    1342                 :            :                            "into Beacon/Probe Response frames");
    1343                 :          0 :                 wpabuf_put_data(beacon, ms_wps, sizeof(ms_wps));
    1344                 :          0 :                 wpabuf_put_data(probe, ms_wps, sizeof(ms_wps));
    1345                 :            :         }
    1346                 :            : 
    1347                 :        621 :         return wps_cb_set_ie(reg, beacon, probe);
    1348                 :            : }
    1349                 :            : 
    1350                 :            : 
    1351                 :        149 : static int wps_get_dev_password(struct wps_data *wps)
    1352                 :            : {
    1353                 :            :         const u8 *pin;
    1354                 :        149 :         size_t pin_len = 0;
    1355                 :            : 
    1356                 :        149 :         os_free(wps->dev_password);
    1357                 :        149 :         wps->dev_password = NULL;
    1358                 :            : 
    1359         [ +  + ]:        149 :         if (wps->pbc) {
    1360                 :         15 :                 wpa_printf(MSG_DEBUG, "WPS: Use default PIN for PBC");
    1361                 :         15 :                 pin = (const u8 *) "00000000";
    1362                 :         15 :                 pin_len = 8;
    1363                 :            : #ifdef CONFIG_WPS_NFC
    1364         [ +  + ]:        134 :         } else if (wps->nfc_pw_token) {
    1365         [ +  + ]:         21 :                 if (wps->nfc_pw_token->pw_id == DEV_PW_NFC_CONNECTION_HANDOVER)
    1366                 :            :                 {
    1367                 :         13 :                         wpa_printf(MSG_DEBUG, "WPS: Using NFC connection "
    1368                 :            :                                    "handover and abbreviated WPS handshake "
    1369                 :            :                                    "without Device Password");
    1370                 :         13 :                         return 0;
    1371                 :            :                 }
    1372                 :          8 :                 wpa_printf(MSG_DEBUG, "WPS: Use OOB Device Password from NFC "
    1373                 :            :                            "Password Token");
    1374                 :          8 :                 pin = wps->nfc_pw_token->dev_pw;
    1375                 :          8 :                 pin_len = wps->nfc_pw_token->dev_pw_len;
    1376 [ +  + ][ +  + ]:        113 :         } else if (wps->dev_pw_id >= 0x10 &&
    1377         [ +  - ]:          2 :                    wps->wps->ap_nfc_dev_pw_id == wps->dev_pw_id &&
    1378                 :          2 :                    wps->wps->ap_nfc_dev_pw) {
    1379                 :          2 :                 wpa_printf(MSG_DEBUG, "WPS: Use OOB Device Password from own NFC Password Token");
    1380                 :          2 :                 pin = wpabuf_head(wps->wps->ap_nfc_dev_pw);
    1381                 :          2 :                 pin_len = wpabuf_len(wps->wps->ap_nfc_dev_pw);
    1382                 :            : #endif /* CONFIG_WPS_NFC */
    1383                 :            :         } else {
    1384                 :        111 :                 pin = wps_registrar_get_pin(wps->wps->registrar, wps->uuid_e,
    1385                 :            :                                             &pin_len);
    1386 [ -  + ][ +  + ]:        111 :                 if (pin && wps->dev_pw_id >= 0x10) {
    1387                 :          0 :                         wpa_printf(MSG_DEBUG, "WPS: No match for OOB Device "
    1388                 :            :                                    "Password ID, but PIN found");
    1389                 :            :                         /*
    1390                 :            :                          * See whether Enrollee is willing to use PIN instead.
    1391                 :            :                          */
    1392                 :          0 :                         wps->dev_pw_id = DEV_PW_DEFAULT;
    1393                 :            :                 }
    1394                 :            :         }
    1395         [ +  + ]:        136 :         if (pin == NULL) {
    1396                 :          8 :                 wpa_printf(MSG_DEBUG, "WPS: No Device Password available for "
    1397                 :            :                            "the Enrollee (context %p registrar %p)",
    1398                 :          8 :                            wps->wps, wps->wps->registrar);
    1399                 :          8 :                 wps_cb_pin_needed(wps->wps->registrar, wps->uuid_e,
    1400                 :          8 :                                   &wps->peer_dev);
    1401                 :          8 :                 return -1;
    1402                 :            :         }
    1403                 :            : 
    1404                 :        128 :         wps->dev_password = os_malloc(pin_len);
    1405         [ -  + ]:        128 :         if (wps->dev_password == NULL)
    1406                 :          0 :                 return -1;
    1407                 :        128 :         os_memcpy(wps->dev_password, pin, pin_len);
    1408                 :        128 :         wps->dev_password_len = pin_len;
    1409                 :            : 
    1410                 :        149 :         return 0;
    1411                 :            : }
    1412                 :            : 
    1413                 :            : 
    1414                 :        154 : static int wps_build_uuid_r(struct wps_data *wps, struct wpabuf *msg)
    1415                 :            : {
    1416                 :        154 :         wpa_printf(MSG_DEBUG, "WPS:  * UUID-R");
    1417                 :        154 :         wpabuf_put_be16(msg, ATTR_UUID_R);
    1418                 :        154 :         wpabuf_put_be16(msg, WPS_UUID_LEN);
    1419                 :        154 :         wpabuf_put_data(msg, wps->uuid_r, WPS_UUID_LEN);
    1420                 :        154 :         return 0;
    1421                 :            : }
    1422                 :            : 
    1423                 :            : 
    1424                 :        122 : static int wps_build_r_hash(struct wps_data *wps, struct wpabuf *msg)
    1425                 :            : {
    1426                 :            :         u8 *hash;
    1427                 :            :         const u8 *addr[4];
    1428                 :            :         size_t len[4];
    1429                 :            : 
    1430         [ -  + ]:        122 :         if (random_get_bytes(wps->snonce, 2 * WPS_SECRET_NONCE_LEN) < 0)
    1431                 :          0 :                 return -1;
    1432                 :        122 :         wpa_hexdump(MSG_DEBUG, "WPS: R-S1", wps->snonce, WPS_SECRET_NONCE_LEN);
    1433                 :        122 :         wpa_hexdump(MSG_DEBUG, "WPS: R-S2",
    1434                 :            :                     wps->snonce + WPS_SECRET_NONCE_LEN, WPS_SECRET_NONCE_LEN);
    1435                 :            : 
    1436 [ -  + ][ +  - ]:        122 :         if (wps->dh_pubkey_e == NULL || wps->dh_pubkey_r == NULL) {
    1437                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: DH public keys not available for "
    1438                 :            :                            "R-Hash derivation");
    1439                 :          0 :                 return -1;
    1440                 :            :         }
    1441                 :            : 
    1442                 :        122 :         wpa_printf(MSG_DEBUG, "WPS:  * R-Hash1");
    1443                 :        122 :         wpabuf_put_be16(msg, ATTR_R_HASH1);
    1444                 :        122 :         wpabuf_put_be16(msg, SHA256_MAC_LEN);
    1445                 :        122 :         hash = wpabuf_put(msg, SHA256_MAC_LEN);
    1446                 :            :         /* R-Hash1 = HMAC_AuthKey(R-S1 || PSK1 || PK_E || PK_R) */
    1447                 :        122 :         addr[0] = wps->snonce;
    1448                 :        122 :         len[0] = WPS_SECRET_NONCE_LEN;
    1449                 :        122 :         addr[1] = wps->psk1;
    1450                 :        122 :         len[1] = WPS_PSK_LEN;
    1451                 :        122 :         addr[2] = wpabuf_head(wps->dh_pubkey_e);
    1452                 :        122 :         len[2] = wpabuf_len(wps->dh_pubkey_e);
    1453                 :        122 :         addr[3] = wpabuf_head(wps->dh_pubkey_r);
    1454                 :        122 :         len[3] = wpabuf_len(wps->dh_pubkey_r);
    1455                 :        122 :         hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
    1456                 :        122 :         wpa_hexdump(MSG_DEBUG, "WPS: R-Hash1", hash, SHA256_MAC_LEN);
    1457                 :            : 
    1458                 :        122 :         wpa_printf(MSG_DEBUG, "WPS:  * R-Hash2");
    1459                 :        122 :         wpabuf_put_be16(msg, ATTR_R_HASH2);
    1460                 :        122 :         wpabuf_put_be16(msg, SHA256_MAC_LEN);
    1461                 :        122 :         hash = wpabuf_put(msg, SHA256_MAC_LEN);
    1462                 :            :         /* R-Hash2 = HMAC_AuthKey(R-S2 || PSK2 || PK_E || PK_R) */
    1463                 :        122 :         addr[0] = wps->snonce + WPS_SECRET_NONCE_LEN;
    1464                 :        122 :         addr[1] = wps->psk2;
    1465                 :        122 :         hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
    1466                 :        122 :         wpa_hexdump(MSG_DEBUG, "WPS: R-Hash2", hash, SHA256_MAC_LEN);
    1467                 :            : 
    1468                 :        122 :         return 0;
    1469                 :            : }
    1470                 :            : 
    1471                 :            : 
    1472                 :        122 : static int wps_build_r_snonce1(struct wps_data *wps, struct wpabuf *msg)
    1473                 :            : {
    1474                 :        122 :         wpa_printf(MSG_DEBUG, "WPS:  * R-SNonce1");
    1475                 :        122 :         wpabuf_put_be16(msg, ATTR_R_SNONCE1);
    1476                 :        122 :         wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN);
    1477                 :        122 :         wpabuf_put_data(msg, wps->snonce, WPS_SECRET_NONCE_LEN);
    1478                 :        122 :         return 0;
    1479                 :            : }
    1480                 :            : 
    1481                 :            : 
    1482                 :        116 : static int wps_build_r_snonce2(struct wps_data *wps, struct wpabuf *msg)
    1483                 :            : {
    1484                 :        116 :         wpa_printf(MSG_DEBUG, "WPS:  * R-SNonce2");
    1485                 :        116 :         wpabuf_put_be16(msg, ATTR_R_SNONCE2);
    1486                 :        116 :         wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN);
    1487                 :        116 :         wpabuf_put_data(msg, wps->snonce + WPS_SECRET_NONCE_LEN,
    1488                 :            :                         WPS_SECRET_NONCE_LEN);
    1489                 :        116 :         return 0;
    1490                 :            : }
    1491                 :            : 
    1492                 :            : 
    1493                 :        130 : static int wps_build_cred_network_idx(struct wpabuf *msg,
    1494                 :            :                                       const struct wps_credential *cred)
    1495                 :            : {
    1496                 :        130 :         wpa_printf(MSG_DEBUG, "WPS:  * Network Index (1)");
    1497                 :        130 :         wpabuf_put_be16(msg, ATTR_NETWORK_INDEX);
    1498                 :        130 :         wpabuf_put_be16(msg, 1);
    1499                 :        130 :         wpabuf_put_u8(msg, 1);
    1500                 :        130 :         return 0;
    1501                 :            : }
    1502                 :            : 
    1503                 :            : 
    1504                 :        130 : static int wps_build_cred_ssid(struct wpabuf *msg,
    1505                 :            :                                const struct wps_credential *cred)
    1506                 :            : {
    1507                 :        130 :         wpa_printf(MSG_DEBUG, "WPS:  * SSID");
    1508                 :        130 :         wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID for Credential",
    1509                 :        130 :                           cred->ssid, cred->ssid_len);
    1510                 :        130 :         wpabuf_put_be16(msg, ATTR_SSID);
    1511                 :        130 :         wpabuf_put_be16(msg, cred->ssid_len);
    1512                 :        130 :         wpabuf_put_data(msg, cred->ssid, cred->ssid_len);
    1513                 :        130 :         return 0;
    1514                 :            : }
    1515                 :            : 
    1516                 :            : 
    1517                 :        130 : static int wps_build_cred_auth_type(struct wpabuf *msg,
    1518                 :            :                                     const struct wps_credential *cred)
    1519                 :            : {
    1520                 :        130 :         wpa_printf(MSG_DEBUG, "WPS:  * Authentication Type (0x%x)",
    1521                 :        130 :                    cred->auth_type);
    1522                 :        130 :         wpabuf_put_be16(msg, ATTR_AUTH_TYPE);
    1523                 :        130 :         wpabuf_put_be16(msg, 2);
    1524                 :        130 :         wpabuf_put_be16(msg, cred->auth_type);
    1525                 :        130 :         return 0;
    1526                 :            : }
    1527                 :            : 
    1528                 :            : 
    1529                 :        130 : static int wps_build_cred_encr_type(struct wpabuf *msg,
    1530                 :            :                                     const struct wps_credential *cred)
    1531                 :            : {
    1532                 :        130 :         wpa_printf(MSG_DEBUG, "WPS:  * Encryption Type (0x%x)",
    1533                 :        130 :                    cred->encr_type);
    1534                 :        130 :         wpabuf_put_be16(msg, ATTR_ENCR_TYPE);
    1535                 :        130 :         wpabuf_put_be16(msg, 2);
    1536                 :        130 :         wpabuf_put_be16(msg, cred->encr_type);
    1537                 :        130 :         return 0;
    1538                 :            : }
    1539                 :            : 
    1540                 :            : 
    1541                 :        130 : static int wps_build_cred_network_key(struct wpabuf *msg,
    1542                 :            :                                       const struct wps_credential *cred)
    1543                 :            : {
    1544                 :        130 :         wpa_printf(MSG_DEBUG, "WPS:  * Network Key (len=%d)",
    1545                 :        130 :                    (int) cred->key_len);
    1546                 :        130 :         wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key",
    1547                 :        130 :                         cred->key, cred->key_len);
    1548                 :        130 :         wpabuf_put_be16(msg, ATTR_NETWORK_KEY);
    1549                 :        130 :         wpabuf_put_be16(msg, cred->key_len);
    1550                 :        130 :         wpabuf_put_data(msg, cred->key, cred->key_len);
    1551                 :        130 :         return 0;
    1552                 :            : }
    1553                 :            : 
    1554                 :            : 
    1555                 :        130 : static int wps_build_credential(struct wpabuf *msg,
    1556                 :            :                                 const struct wps_credential *cred)
    1557                 :            : {
    1558   [ +  -  +  - ]:        260 :         if (wps_build_cred_network_idx(msg, cred) ||
    1559         [ +  - ]:        260 :             wps_build_cred_ssid(msg, cred) ||
    1560         [ +  - ]:        260 :             wps_build_cred_auth_type(msg, cred) ||
    1561         [ +  - ]:        260 :             wps_build_cred_encr_type(msg, cred) ||
    1562         [ -  + ]:        260 :             wps_build_cred_network_key(msg, cred) ||
    1563                 :        130 :             wps_build_mac_addr(msg, cred->mac_addr))
    1564                 :          0 :                 return -1;
    1565                 :        130 :         return 0;
    1566                 :            : }
    1567                 :            : 
    1568                 :            : 
    1569                 :          0 : int wps_build_credential_wrap(struct wpabuf *msg,
    1570                 :            :                               const struct wps_credential *cred)
    1571                 :            : {
    1572                 :            :         struct wpabuf *wbuf;
    1573                 :          0 :         wbuf = wpabuf_alloc(200);
    1574         [ #  # ]:          0 :         if (wbuf == NULL)
    1575                 :          0 :                 return -1;
    1576         [ #  # ]:          0 :         if (wps_build_credential(wbuf, cred)) {
    1577                 :          0 :                 wpabuf_free(wbuf);
    1578                 :          0 :                 return -1;
    1579                 :            :         }
    1580                 :          0 :         wpabuf_put_be16(msg, ATTR_CRED);
    1581                 :          0 :         wpabuf_put_be16(msg, wpabuf_len(wbuf));
    1582                 :          0 :         wpabuf_put_buf(msg, wbuf);
    1583                 :          0 :         wpabuf_free(wbuf);
    1584                 :          0 :         return 0;
    1585                 :            : }
    1586                 :            : 
    1587                 :            : 
    1588                 :        112 : int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
    1589                 :            : {
    1590                 :            :         struct wpabuf *cred;
    1591                 :            : 
    1592         [ -  + ]:        112 :         if (wps->wps->registrar->skip_cred_build)
    1593                 :          0 :                 goto skip_cred_build;
    1594                 :            : 
    1595                 :        112 :         wpa_printf(MSG_DEBUG, "WPS:  * Credential");
    1596         [ +  + ]:        112 :         if (wps->use_cred) {
    1597                 :          8 :                 os_memcpy(&wps->cred, wps->use_cred, sizeof(wps->cred));
    1598                 :          8 :                 goto use_provided;
    1599                 :            :         }
    1600                 :        104 :         os_memset(&wps->cred, 0, sizeof(wps->cred));
    1601                 :            : 
    1602                 :        104 :         os_memcpy(wps->cred.ssid, wps->wps->ssid, wps->wps->ssid_len);
    1603                 :        104 :         wps->cred.ssid_len = wps->wps->ssid_len;
    1604                 :            : 
    1605                 :            :         /* Select the best authentication and encryption type */
    1606         [ +  - ]:        104 :         if (wps->auth_type & WPS_AUTH_WPA2PSK)
    1607                 :        104 :                 wps->auth_type = WPS_AUTH_WPA2PSK;
    1608         [ #  # ]:          0 :         else if (wps->auth_type & WPS_AUTH_WPAPSK)
    1609                 :          0 :                 wps->auth_type = WPS_AUTH_WPAPSK;
    1610         [ #  # ]:          0 :         else if (wps->auth_type & WPS_AUTH_OPEN)
    1611                 :          0 :                 wps->auth_type = WPS_AUTH_OPEN;
    1612         [ #  # ]:          0 :         else if (wps->auth_type & WPS_AUTH_SHARED)
    1613                 :          0 :                 wps->auth_type = WPS_AUTH_SHARED;
    1614                 :            :         else {
    1615                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Unsupported auth_type 0x%x",
    1616                 :          0 :                            wps->auth_type);
    1617                 :          0 :                 return -1;
    1618                 :            :         }
    1619                 :        104 :         wps->cred.auth_type = wps->auth_type;
    1620                 :            : 
    1621 [ -  + ][ #  # ]:        104 :         if (wps->auth_type == WPS_AUTH_WPA2PSK ||
    1622                 :          0 :             wps->auth_type == WPS_AUTH_WPAPSK) {
    1623         [ +  - ]:        208 :                 if (wps->encr_type & WPS_ENCR_AES)
    1624                 :        104 :                         wps->encr_type = WPS_ENCR_AES;
    1625         [ #  # ]:          0 :                 else if (wps->encr_type & WPS_ENCR_TKIP)
    1626                 :          0 :                         wps->encr_type = WPS_ENCR_TKIP;
    1627                 :            :                 else {
    1628                 :          0 :                         wpa_printf(MSG_DEBUG, "WPS: No suitable encryption "
    1629                 :            :                                    "type for WPA/WPA2");
    1630                 :          0 :                         return -1;
    1631                 :            :                 }
    1632                 :            :         } else {
    1633         [ #  # ]:          0 :                 if (wps->encr_type & WPS_ENCR_WEP)
    1634                 :          0 :                         wps->encr_type = WPS_ENCR_WEP;
    1635         [ #  # ]:          0 :                 else if (wps->encr_type & WPS_ENCR_NONE)
    1636                 :          0 :                         wps->encr_type = WPS_ENCR_NONE;
    1637                 :            :                 else {
    1638                 :          0 :                         wpa_printf(MSG_DEBUG, "WPS: No suitable encryption "
    1639                 :            :                                    "type for non-WPA/WPA2 mode");
    1640                 :          0 :                         return -1;
    1641                 :            :                 }
    1642                 :            :         }
    1643                 :        104 :         wps->cred.encr_type = wps->encr_type;
    1644                 :            :         /*
    1645                 :            :          * Set MAC address in the Credential to be the Enrollee's MAC address
    1646                 :            :          */
    1647                 :        104 :         os_memcpy(wps->cred.mac_addr, wps->mac_addr_e, ETH_ALEN);
    1648                 :            : 
    1649 [ +  + ][ +  - ]:        104 :         if (wps->wps->wps_state == WPS_STATE_NOT_CONFIGURED && wps->wps->ap &&
                 [ +  - ]
    1650                 :          6 :             !wps->wps->registrar->disable_auto_conf) {
    1651                 :            :                 u8 r[16];
    1652                 :            :                 /* Generate a random passphrase */
    1653         [ -  + ]:          6 :                 if (random_get_bytes(r, sizeof(r)) < 0)
    1654                 :          0 :                         return -1;
    1655                 :          6 :                 os_free(wps->new_psk);
    1656                 :          6 :                 wps->new_psk = base64_encode(r, sizeof(r), &wps->new_psk_len);
    1657         [ -  + ]:          6 :                 if (wps->new_psk == NULL)
    1658                 :          0 :                         return -1;
    1659                 :          6 :                 wps->new_psk_len--; /* remove newline */
    1660 [ +  - ][ +  + ]:         18 :                 while (wps->new_psk_len &&
    1661                 :         18 :                        wps->new_psk[wps->new_psk_len - 1] == '=')
    1662                 :         12 :                         wps->new_psk_len--;
    1663                 :          6 :                 wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Generated passphrase",
    1664                 :          6 :                                       wps->new_psk, wps->new_psk_len);
    1665                 :          6 :                 os_memcpy(wps->cred.key, wps->new_psk, wps->new_psk_len);
    1666                 :          6 :                 wps->cred.key_len = wps->new_psk_len;
    1667 [ +  + ][ +  + ]:         98 :         } else if (!wps->wps->registrar->force_per_enrollee_psk &&
    1668         [ +  - ]:        140 :                    wps->use_psk_key && wps->wps->psk_set) {
    1669                 :            :                 char hex[65];
    1670                 :         70 :                 wpa_printf(MSG_DEBUG, "WPS: Use PSK format for Network Key");
    1671                 :         70 :                 wpa_snprintf_hex(hex, sizeof(hex), wps->wps->psk, 32);
    1672                 :         70 :                 os_memcpy(wps->cred.key, hex, 32 * 2);
    1673                 :         70 :                 wps->cred.key_len = 32 * 2;
    1674 [ +  + ][ +  - ]:         28 :         } else if (!wps->wps->registrar->force_per_enrollee_psk &&
    1675                 :         20 :                    wps->wps->network_key) {
    1676                 :         20 :                 os_memcpy(wps->cred.key, wps->wps->network_key,
    1677                 :            :                           wps->wps->network_key_len);
    1678                 :         20 :                 wps->cred.key_len = wps->wps->network_key_len;
    1679         [ +  - ]:          8 :         } else if (wps->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) {
    1680                 :            :                 char hex[65];
    1681                 :            :                 /* Generate a random per-device PSK */
    1682                 :          8 :                 os_free(wps->new_psk);
    1683                 :          8 :                 wps->new_psk_len = 32;
    1684                 :          8 :                 wps->new_psk = os_malloc(wps->new_psk_len);
    1685         [ -  + ]:          8 :                 if (wps->new_psk == NULL)
    1686                 :          0 :                         return -1;
    1687         [ -  + ]:          8 :                 if (random_get_bytes(wps->new_psk, wps->new_psk_len) < 0) {
    1688                 :          0 :                         os_free(wps->new_psk);
    1689                 :          0 :                         wps->new_psk = NULL;
    1690                 :          0 :                         return -1;
    1691                 :            :                 }
    1692                 :          8 :                 wpa_hexdump_key(MSG_DEBUG, "WPS: Generated per-device PSK",
    1693                 :          8 :                                 wps->new_psk, wps->new_psk_len);
    1694                 :          8 :                 wpa_snprintf_hex(hex, sizeof(hex), wps->new_psk,
    1695                 :            :                                  wps->new_psk_len);
    1696                 :          8 :                 os_memcpy(wps->cred.key, hex, wps->new_psk_len * 2);
    1697                 :          8 :                 wps->cred.key_len = wps->new_psk_len * 2;
    1698                 :            :         }
    1699                 :            : 
    1700                 :            : use_provided:
    1701                 :            : #ifdef CONFIG_WPS_TESTING
    1702         [ -  + ]:        112 :         if (wps_testing_dummy_cred)
    1703                 :          0 :                 cred = wpabuf_alloc(200);
    1704                 :            :         else
    1705                 :        112 :                 cred = NULL;
    1706         [ -  + ]:        112 :         if (cred) {
    1707                 :            :                 struct wps_credential dummy;
    1708                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Add dummy credential");
    1709                 :          0 :                 os_memset(&dummy, 0, sizeof(dummy));
    1710                 :          0 :                 os_memcpy(dummy.ssid, "dummy", 5);
    1711                 :          0 :                 dummy.ssid_len = 5;
    1712                 :          0 :                 dummy.auth_type = WPS_AUTH_WPA2PSK;
    1713                 :          0 :                 dummy.encr_type = WPS_ENCR_AES;
    1714                 :          0 :                 os_memcpy(dummy.key, "dummy psk", 9);
    1715                 :          0 :                 dummy.key_len = 9;
    1716                 :          0 :                 os_memcpy(dummy.mac_addr, wps->mac_addr_e, ETH_ALEN);
    1717                 :          0 :                 wps_build_credential(cred, &dummy);
    1718                 :          0 :                 wpa_hexdump_buf(MSG_DEBUG, "WPS: Dummy Credential", cred);
    1719                 :            : 
    1720                 :          0 :                 wpabuf_put_be16(msg, ATTR_CRED);
    1721                 :          0 :                 wpabuf_put_be16(msg, wpabuf_len(cred));
    1722                 :          0 :                 wpabuf_put_buf(msg, cred);
    1723                 :            : 
    1724                 :          0 :                 wpabuf_free(cred);
    1725                 :            :         }
    1726                 :            : #endif /* CONFIG_WPS_TESTING */
    1727                 :            : 
    1728                 :        112 :         cred = wpabuf_alloc(200);
    1729         [ -  + ]:        112 :         if (cred == NULL)
    1730                 :          0 :                 return -1;
    1731                 :            : 
    1732         [ -  + ]:        112 :         if (wps_build_credential(cred, &wps->cred)) {
    1733                 :          0 :                 wpabuf_free(cred);
    1734                 :          0 :                 return -1;
    1735                 :            :         }
    1736                 :            : 
    1737                 :        112 :         wpabuf_put_be16(msg, ATTR_CRED);
    1738                 :        112 :         wpabuf_put_be16(msg, wpabuf_len(cred));
    1739                 :        112 :         wpabuf_put_buf(msg, cred);
    1740                 :        112 :         wpabuf_free(cred);
    1741                 :            : 
    1742                 :            : skip_cred_build:
    1743         [ -  + ]:        112 :         if (wps->wps->registrar->extra_cred) {
    1744                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS:  * Credential (pre-configured)");
    1745                 :          0 :                 wpabuf_put_buf(msg, wps->wps->registrar->extra_cred);
    1746                 :            :         }
    1747                 :            : 
    1748                 :        112 :         return 0;
    1749                 :            : }
    1750                 :            : 
    1751                 :            : 
    1752                 :         18 : static int wps_build_ap_settings(struct wps_data *wps, struct wpabuf *msg)
    1753                 :            : {
    1754                 :         18 :         wpa_printf(MSG_DEBUG, "WPS:  * AP Settings");
    1755                 :            : 
    1756         [ -  + ]:         18 :         if (wps_build_credential(msg, &wps->cred))
    1757                 :          0 :                 return -1;
    1758                 :            : 
    1759                 :         18 :         return 0;
    1760                 :            : }
    1761                 :            : 
    1762                 :            : 
    1763                 :         12 : static struct wpabuf * wps_build_ap_cred(struct wps_data *wps)
    1764                 :            : {
    1765                 :            :         struct wpabuf *msg, *plain;
    1766                 :            : 
    1767                 :         12 :         msg = wpabuf_alloc(1000);
    1768         [ -  + ]:         12 :         if (msg == NULL)
    1769                 :          0 :                 return NULL;
    1770                 :            : 
    1771                 :         12 :         plain = wpabuf_alloc(200);
    1772         [ -  + ]:         12 :         if (plain == NULL) {
    1773                 :          0 :                 wpabuf_free(msg);
    1774                 :          0 :                 return NULL;
    1775                 :            :         }
    1776                 :            : 
    1777         [ -  + ]:         12 :         if (wps_build_ap_settings(wps, plain)) {
    1778                 :          0 :                 wpabuf_free(plain);
    1779                 :          0 :                 wpabuf_free(msg);
    1780                 :          0 :                 return NULL;
    1781                 :            :         }
    1782                 :            : 
    1783                 :         12 :         wpabuf_put_be16(msg, ATTR_CRED);
    1784                 :         12 :         wpabuf_put_be16(msg, wpabuf_len(plain));
    1785                 :         12 :         wpabuf_put_buf(msg, plain);
    1786                 :         12 :         wpabuf_free(plain);
    1787                 :            : 
    1788                 :         12 :         return msg;
    1789                 :            : }
    1790                 :            : 
    1791                 :            : 
    1792                 :        141 : static struct wpabuf * wps_build_m2(struct wps_data *wps)
    1793                 :            : {
    1794                 :            :         struct wpabuf *msg;
    1795                 :        141 :         int config_in_m2 = 0;
    1796                 :            : 
    1797         [ -  + ]:        141 :         if (random_get_bytes(wps->nonce_r, WPS_NONCE_LEN) < 0)
    1798                 :          0 :                 return NULL;
    1799                 :        141 :         wpa_hexdump(MSG_DEBUG, "WPS: Registrar Nonce",
    1800                 :        141 :                     wps->nonce_r, WPS_NONCE_LEN);
    1801                 :        141 :         wpa_hexdump(MSG_DEBUG, "WPS: UUID-R", wps->uuid_r, WPS_UUID_LEN);
    1802                 :            : 
    1803                 :        141 :         wpa_printf(MSG_DEBUG, "WPS: Building Message M2");
    1804                 :        141 :         msg = wpabuf_alloc(1000);
    1805         [ -  + ]:        141 :         if (msg == NULL)
    1806                 :          0 :                 return NULL;
    1807                 :            : 
    1808   [ +  -  +  - ]:        282 :         if (wps_build_version(msg) ||
    1809         [ +  - ]:        282 :             wps_build_msg_type(msg, WPS_M2) ||
    1810         [ +  - ]:        282 :             wps_build_enrollee_nonce(wps, msg) ||
    1811         [ +  - ]:        282 :             wps_build_registrar_nonce(wps, msg) ||
    1812         [ +  - ]:        282 :             wps_build_uuid_r(wps, msg) ||
    1813         [ +  - ]:        282 :             wps_build_public_key(wps, msg) ||
    1814         [ +  - ]:        282 :             wps_derive_keys(wps) ||
    1815         [ +  - ]:        282 :             wps_build_auth_type_flags(wps, msg) ||
    1816         [ +  - ]:        282 :             wps_build_encr_type_flags(wps, msg) ||
    1817         [ +  - ]:        282 :             wps_build_conn_type_flags(wps, msg) ||
    1818         [ +  - ]:        282 :             wps_build_config_methods_r(wps->wps->registrar, msg) ||
    1819         [ +  - ]:        282 :             wps_build_device_attrs(&wps->wps->dev, msg) ||
    1820                 :        141 :             wps_build_rf_bands(&wps->wps->dev, msg,
    1821         [ +  - ]:        282 :                                wps->wps->rf_band_cb(wps->wps->cb_ctx)) ||
    1822         [ +  - ]:        282 :             wps_build_assoc_state(wps, msg) ||
    1823         [ +  - ]:        282 :             wps_build_config_error(msg, WPS_CFG_NO_ERROR) ||
    1824         [ +  - ]:        282 :             wps_build_dev_password_id(msg, wps->dev_pw_id) ||
    1825         [ -  + ]:        282 :             wps_build_os_version(&wps->wps->dev, msg) ||
    1826                 :        141 :             wps_build_wfa_ext(msg, 0, NULL, 0)) {
    1827                 :          0 :                 wpabuf_free(msg);
    1828                 :          0 :                 return NULL;
    1829                 :            :         }
    1830                 :            : 
    1831                 :            : #ifdef CONFIG_WPS_NFC
    1832 [ +  + ][ +  + ]:        141 :         if (wps->nfc_pw_token && wps->nfc_pw_token->pk_hash_provided_oob &&
                 [ +  + ]
    1833                 :         17 :             wps->nfc_pw_token->pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) {
    1834                 :            :                 /*
    1835                 :            :                  * Use abbreviated handshake since public key hash allowed
    1836                 :            :                  * Enrollee to validate our public key similarly to how Enrollee
    1837                 :            :                  * public key was validated. There is no need to validate Device
    1838                 :            :                  * Password in this case.
    1839                 :            :                  */
    1840                 :         13 :                 struct wpabuf *plain = wpabuf_alloc(500);
    1841   [ +  -  +  - ]:         26 :                 if (plain == NULL ||
    1842         [ +  - ]:         26 :                     wps_build_cred(wps, plain) ||
    1843         [ -  + ]:         26 :                     wps_build_key_wrap_auth(wps, plain) ||
    1844                 :         13 :                     wps_build_encr_settings(wps, msg, plain)) {
    1845                 :          0 :                         wpabuf_free(msg);
    1846                 :          0 :                         wpabuf_free(plain);
    1847                 :          0 :                         return NULL;
    1848                 :            :                 }
    1849                 :         13 :                 wpabuf_free(plain);
    1850                 :         13 :                 config_in_m2 = 1;
    1851                 :            :         }
    1852                 :            : #endif /* CONFIG_WPS_NFC */
    1853                 :            : 
    1854         [ -  + ]:        141 :         if (wps_build_authenticator(wps, msg)) {
    1855                 :          0 :                 wpabuf_free(msg);
    1856                 :          0 :                 return NULL;
    1857                 :            :         }
    1858                 :            : 
    1859                 :        141 :         wps->int_reg = 1;
    1860         [ +  + ]:        141 :         wps->state = config_in_m2 ? RECV_DONE : RECV_M3;
    1861                 :        141 :         return msg;
    1862                 :            : }
    1863                 :            : 
    1864                 :            : 
    1865                 :         13 : static struct wpabuf * wps_build_m2d(struct wps_data *wps)
    1866                 :            : {
    1867                 :            :         struct wpabuf *msg;
    1868                 :         13 :         u16 err = wps->config_error;
    1869                 :            : 
    1870                 :         13 :         wpa_printf(MSG_DEBUG, "WPS: Building Message M2D");
    1871                 :         13 :         msg = wpabuf_alloc(1000);
    1872         [ -  + ]:         13 :         if (msg == NULL)
    1873                 :          0 :                 return NULL;
    1874                 :            : 
    1875 [ +  + ][ -  + ]:         13 :         if (wps->wps->ap && wps->wps->ap_setup_locked &&
                 [ #  # ]
    1876                 :            :             err == WPS_CFG_NO_ERROR)
    1877                 :          0 :                 err = WPS_CFG_SETUP_LOCKED;
    1878                 :            : 
    1879   [ +  -  +  - ]:         26 :         if (wps_build_version(msg) ||
    1880         [ +  - ]:         26 :             wps_build_msg_type(msg, WPS_M2D) ||
    1881         [ +  - ]:         26 :             wps_build_enrollee_nonce(wps, msg) ||
    1882         [ +  - ]:         26 :             wps_build_registrar_nonce(wps, msg) ||
    1883         [ +  - ]:         26 :             wps_build_uuid_r(wps, msg) ||
    1884         [ +  - ]:         26 :             wps_build_auth_type_flags(wps, msg) ||
    1885         [ +  - ]:         26 :             wps_build_encr_type_flags(wps, msg) ||
    1886         [ +  - ]:         26 :             wps_build_conn_type_flags(wps, msg) ||
    1887         [ +  - ]:         26 :             wps_build_config_methods_r(wps->wps->registrar, msg) ||
    1888         [ +  - ]:         26 :             wps_build_device_attrs(&wps->wps->dev, msg) ||
    1889                 :         13 :             wps_build_rf_bands(&wps->wps->dev, msg,
    1890         [ +  - ]:         26 :                                wps->wps->rf_band_cb(wps->wps->cb_ctx)) ||
    1891         [ +  - ]:         26 :             wps_build_assoc_state(wps, msg) ||
    1892         [ +  - ]:         26 :             wps_build_config_error(msg, err) ||
    1893         [ -  + ]:         26 :             wps_build_os_version(&wps->wps->dev, msg) ||
    1894                 :         13 :             wps_build_wfa_ext(msg, 0, NULL, 0)) {
    1895                 :          0 :                 wpabuf_free(msg);
    1896                 :          0 :                 return NULL;
    1897                 :            :         }
    1898                 :            : 
    1899                 :         13 :         wps->state = RECV_M2D_ACK;
    1900                 :         13 :         return msg;
    1901                 :            : }
    1902                 :            : 
    1903                 :            : 
    1904                 :        122 : static struct wpabuf * wps_build_m4(struct wps_data *wps)
    1905                 :            : {
    1906                 :            :         struct wpabuf *msg, *plain;
    1907                 :            : 
    1908                 :        122 :         wpa_printf(MSG_DEBUG, "WPS: Building Message M4");
    1909                 :            : 
    1910                 :        122 :         wps_derive_psk(wps, wps->dev_password, wps->dev_password_len);
    1911                 :            : 
    1912                 :        122 :         plain = wpabuf_alloc(200);
    1913         [ -  + ]:        122 :         if (plain == NULL)
    1914                 :          0 :                 return NULL;
    1915                 :            : 
    1916                 :        122 :         msg = wpabuf_alloc(1000);
    1917         [ -  + ]:        122 :         if (msg == NULL) {
    1918                 :          0 :                 wpabuf_free(plain);
    1919                 :          0 :                 return NULL;
    1920                 :            :         }
    1921                 :            : 
    1922   [ +  -  +  - ]:        244 :         if (wps_build_version(msg) ||
    1923         [ +  - ]:        244 :             wps_build_msg_type(msg, WPS_M4) ||
    1924         [ +  - ]:        244 :             wps_build_enrollee_nonce(wps, msg) ||
    1925         [ +  - ]:        244 :             wps_build_r_hash(wps, msg) ||
    1926         [ +  - ]:        244 :             wps_build_r_snonce1(wps, plain) ||
    1927         [ +  - ]:        244 :             wps_build_key_wrap_auth(wps, plain) ||
    1928         [ +  - ]:        244 :             wps_build_encr_settings(wps, msg, plain) ||
    1929         [ -  + ]:        244 :             wps_build_wfa_ext(msg, 0, NULL, 0) ||
    1930                 :        122 :             wps_build_authenticator(wps, msg)) {
    1931                 :          0 :                 wpabuf_free(plain);
    1932                 :          0 :                 wpabuf_free(msg);
    1933                 :          0 :                 return NULL;
    1934                 :            :         }
    1935                 :        122 :         wpabuf_free(plain);
    1936                 :            : 
    1937                 :        122 :         wps->state = RECV_M5;
    1938                 :        122 :         return msg;
    1939                 :            : }
    1940                 :            : 
    1941                 :            : 
    1942                 :        116 : static struct wpabuf * wps_build_m6(struct wps_data *wps)
    1943                 :            : {
    1944                 :            :         struct wpabuf *msg, *plain;
    1945                 :            : 
    1946                 :        116 :         wpa_printf(MSG_DEBUG, "WPS: Building Message M6");
    1947                 :            : 
    1948                 :        116 :         plain = wpabuf_alloc(200);
    1949         [ -  + ]:        116 :         if (plain == NULL)
    1950                 :          0 :                 return NULL;
    1951                 :            : 
    1952                 :        116 :         msg = wpabuf_alloc(1000);
    1953         [ -  + ]:        116 :         if (msg == NULL) {
    1954                 :          0 :                 wpabuf_free(plain);
    1955                 :          0 :                 return NULL;
    1956                 :            :         }
    1957                 :            : 
    1958   [ +  -  +  - ]:        232 :         if (wps_build_version(msg) ||
    1959         [ +  - ]:        232 :             wps_build_msg_type(msg, WPS_M6) ||
    1960         [ +  - ]:        232 :             wps_build_enrollee_nonce(wps, msg) ||
    1961         [ +  - ]:        232 :             wps_build_r_snonce2(wps, plain) ||
    1962         [ +  - ]:        232 :             wps_build_key_wrap_auth(wps, plain) ||
    1963         [ +  - ]:        232 :             wps_build_encr_settings(wps, msg, plain) ||
    1964         [ -  + ]:        232 :             wps_build_wfa_ext(msg, 0, NULL, 0) ||
    1965                 :        116 :             wps_build_authenticator(wps, msg)) {
    1966                 :          0 :                 wpabuf_free(plain);
    1967                 :          0 :                 wpabuf_free(msg);
    1968                 :          0 :                 return NULL;
    1969                 :            :         }
    1970                 :        116 :         wpabuf_free(plain);
    1971                 :            : 
    1972                 :        116 :         wps->wps_pin_revealed = 1;
    1973                 :        116 :         wps->state = RECV_M7;
    1974                 :        116 :         return msg;
    1975                 :            : }
    1976                 :            : 
    1977                 :            : 
    1978                 :        101 : static struct wpabuf * wps_build_m8(struct wps_data *wps)
    1979                 :            : {
    1980                 :            :         struct wpabuf *msg, *plain;
    1981                 :            : 
    1982                 :        101 :         wpa_printf(MSG_DEBUG, "WPS: Building Message M8");
    1983                 :            : 
    1984                 :        101 :         plain = wpabuf_alloc(500);
    1985         [ -  + ]:        101 :         if (plain == NULL)
    1986                 :          0 :                 return NULL;
    1987                 :            : 
    1988                 :        101 :         msg = wpabuf_alloc(1000);
    1989         [ -  + ]:        101 :         if (msg == NULL) {
    1990                 :          0 :                 wpabuf_free(plain);
    1991                 :          0 :                 return NULL;
    1992                 :            :         }
    1993                 :            : 
    1994   [ +  -  +  - ]:        202 :         if (wps_build_version(msg) ||
    1995         [ +  - ]:        202 :             wps_build_msg_type(msg, WPS_M8) ||
    1996         [ +  + ]:        202 :             wps_build_enrollee_nonce(wps, msg) ||
    1997 [ +  + ][ +  - ]:        101 :             ((wps->wps->ap || wps->er) && wps_build_cred(wps, plain)) ||
                 [ +  + ]
    1998         [ +  + ]:        112 :             (!wps->wps->ap && !wps->er && wps_build_ap_settings(wps, plain)) ||
           [ +  -  +  - ]
    1999         [ +  - ]:        202 :             wps_build_key_wrap_auth(wps, plain) ||
    2000         [ +  - ]:        202 :             wps_build_encr_settings(wps, msg, plain) ||
    2001         [ -  + ]:        202 :             wps_build_wfa_ext(msg, 0, NULL, 0) ||
    2002                 :        101 :             wps_build_authenticator(wps, msg)) {
    2003                 :          0 :                 wpabuf_free(plain);
    2004                 :          0 :                 wpabuf_free(msg);
    2005                 :          0 :                 return NULL;
    2006                 :            :         }
    2007                 :        101 :         wpabuf_free(plain);
    2008                 :            : 
    2009                 :        101 :         wps->state = RECV_DONE;
    2010                 :        101 :         return msg;
    2011                 :            : }
    2012                 :            : 
    2013                 :            : 
    2014                 :        545 : struct wpabuf * wps_registrar_get_msg(struct wps_data *wps,
    2015                 :            :                                       enum wsc_op_code *op_code)
    2016                 :            : {
    2017                 :            :         struct wpabuf *msg;
    2018                 :            : 
    2019                 :            : #ifdef CONFIG_WPS_UPNP
    2020 [ +  + ][ +  + ]:        545 :         if (!wps->int_reg && wps->wps->wps_upnp) {
    2021                 :         31 :                 struct upnp_pending_message *p, *prev = NULL;
    2022         [ +  + ]:         31 :                 if (wps->ext_reg > 1)
    2023                 :         15 :                         wps_registrar_free_pending_m2(wps->wps);
    2024                 :         31 :                 p = wps->wps->upnp_msgs;
    2025                 :            :                 /* TODO: check pending message MAC address */
    2026 [ +  + ][ -  + ]:         31 :                 while (p && p->next) {
    2027                 :          0 :                         prev = p;
    2028                 :          0 :                         p = p->next;
    2029                 :            :                 }
    2030         [ +  + ]:         31 :                 if (p) {
    2031                 :         23 :                         wpa_printf(MSG_DEBUG, "WPS: Use pending message from "
    2032                 :            :                                    "UPnP");
    2033         [ -  + ]:         23 :                         if (prev)
    2034                 :          0 :                                 prev->next = NULL;
    2035                 :            :                         else
    2036                 :         23 :                                 wps->wps->upnp_msgs = NULL;
    2037                 :         23 :                         msg = p->msg;
    2038      [ -  -  + ]:         23 :                         switch (p->type) {
    2039                 :            :                         case WPS_WSC_ACK:
    2040                 :          0 :                                 *op_code = WSC_ACK;
    2041                 :          0 :                                 break;
    2042                 :            :                         case WPS_WSC_NACK:
    2043                 :          0 :                                 *op_code = WSC_NACK;
    2044                 :          0 :                                 break;
    2045                 :            :                         default:
    2046                 :         23 :                                 *op_code = WSC_MSG;
    2047                 :         23 :                                 break;
    2048                 :            :                         }
    2049                 :         23 :                         os_free(p);
    2050         [ -  + ]:         23 :                         if (wps->ext_reg == 0)
    2051                 :          0 :                                 wps->ext_reg = 1;
    2052                 :         23 :                         return msg;
    2053                 :            :                 }
    2054                 :            :         }
    2055         [ -  + ]:        522 :         if (wps->ext_reg) {
    2056                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Using external Registrar, but no "
    2057                 :            :                            "pending message available");
    2058                 :          0 :                 return NULL;
    2059                 :            :         }
    2060                 :            : #endif /* CONFIG_WPS_UPNP */
    2061                 :            : 
    2062   [ +  +  +  +  :        522 :         switch (wps->state) {
             +  +  +  - ]
    2063                 :            :         case SEND_M2:
    2064         [ +  + ]:        149 :                 if (wps_get_dev_password(wps) < 0)
    2065                 :          8 :                         msg = wps_build_m2d(wps);
    2066                 :            :                 else
    2067                 :        141 :                         msg = wps_build_m2(wps);
    2068                 :        149 :                 *op_code = WSC_MSG;
    2069                 :        149 :                 break;
    2070                 :            :         case SEND_M2D:
    2071                 :          5 :                 msg = wps_build_m2d(wps);
    2072                 :          5 :                 *op_code = WSC_MSG;
    2073                 :          5 :                 break;
    2074                 :            :         case SEND_M4:
    2075                 :        122 :                 msg = wps_build_m4(wps);
    2076                 :        122 :                 *op_code = WSC_MSG;
    2077                 :        122 :                 break;
    2078                 :            :         case SEND_M6:
    2079                 :        116 :                 msg = wps_build_m6(wps);
    2080                 :        116 :                 *op_code = WSC_MSG;
    2081                 :        116 :                 break;
    2082                 :            :         case SEND_M8:
    2083                 :        101 :                 msg = wps_build_m8(wps);
    2084                 :        101 :                 *op_code = WSC_MSG;
    2085                 :        101 :                 break;
    2086                 :            :         case RECV_DONE:
    2087                 :          4 :                 msg = wps_build_wsc_ack(wps);
    2088                 :          4 :                 *op_code = WSC_ACK;
    2089                 :          4 :                 break;
    2090                 :            :         case SEND_WSC_NACK:
    2091                 :         25 :                 msg = wps_build_wsc_nack(wps);
    2092                 :         25 :                 *op_code = WSC_NACK;
    2093                 :         25 :                 break;
    2094                 :            :         default:
    2095                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Unsupported state %d for building "
    2096                 :          0 :                            "a message", wps->state);
    2097                 :          0 :                 msg = NULL;
    2098                 :          0 :                 break;
    2099                 :            :         }
    2100                 :            : 
    2101 [ +  + ][ +  - ]:        522 :         if (*op_code == WSC_MSG && msg) {
    2102                 :            :                 /* Save a copy of the last message for Authenticator derivation
    2103                 :            :                  */
    2104                 :        493 :                 wpabuf_free(wps->last_msg);
    2105                 :        493 :                 wps->last_msg = wpabuf_dup(msg);
    2106                 :            :         }
    2107                 :            : 
    2108                 :        545 :         return msg;
    2109                 :            : }
    2110                 :            : 
    2111                 :            : 
    2112                 :        154 : static int wps_process_enrollee_nonce(struct wps_data *wps, const u8 *e_nonce)
    2113                 :            : {
    2114         [ -  + ]:        154 :         if (e_nonce == NULL) {
    2115                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No Enrollee Nonce received");
    2116                 :          0 :                 return -1;
    2117                 :            :         }
    2118                 :            : 
    2119                 :        154 :         os_memcpy(wps->nonce_e, e_nonce, WPS_NONCE_LEN);
    2120                 :        154 :         wpa_hexdump(MSG_DEBUG, "WPS: Enrollee Nonce",
    2121                 :        154 :                     wps->nonce_e, WPS_NONCE_LEN);
    2122                 :            : 
    2123                 :        154 :         return 0;
    2124                 :            : }
    2125                 :            : 
    2126                 :            : 
    2127                 :        351 : static int wps_process_registrar_nonce(struct wps_data *wps, const u8 *r_nonce)
    2128                 :            : {
    2129         [ -  + ]:        351 :         if (r_nonce == NULL) {
    2130                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No Registrar Nonce received");
    2131                 :          0 :                 return -1;
    2132                 :            :         }
    2133                 :            : 
    2134         [ -  + ]:        351 :         if (os_memcmp(wps->nonce_r, r_nonce, WPS_NONCE_LEN) != 0) {
    2135                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce received");
    2136                 :          0 :                 return -1;
    2137                 :            :         }
    2138                 :            : 
    2139                 :        351 :         return 0;
    2140                 :            : }
    2141                 :            : 
    2142                 :            : 
    2143                 :        154 : static int wps_process_uuid_e(struct wps_data *wps, const u8 *uuid_e)
    2144                 :            : {
    2145         [ -  + ]:        154 :         if (uuid_e == NULL) {
    2146                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No UUID-E received");
    2147                 :          0 :                 return -1;
    2148                 :            :         }
    2149                 :            : 
    2150                 :        154 :         os_memcpy(wps->uuid_e, uuid_e, WPS_UUID_LEN);
    2151                 :        154 :         wpa_hexdump(MSG_DEBUG, "WPS: UUID-E", wps->uuid_e, WPS_UUID_LEN);
    2152                 :            : 
    2153                 :        154 :         return 0;
    2154                 :            : }
    2155                 :            : 
    2156                 :            : 
    2157                 :        154 : static int wps_process_dev_password_id(struct wps_data *wps, const u8 *pw_id)
    2158                 :            : {
    2159         [ -  + ]:        154 :         if (pw_id == NULL) {
    2160                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No Device Password ID received");
    2161                 :          0 :                 return -1;
    2162                 :            :         }
    2163                 :            : 
    2164                 :        154 :         wps->dev_pw_id = WPA_GET_BE16(pw_id);
    2165                 :        154 :         wpa_printf(MSG_DEBUG, "WPS: Device Password ID %d", wps->dev_pw_id);
    2166                 :            : 
    2167                 :        154 :         return 0;
    2168                 :            : }
    2169                 :            : 
    2170                 :            : 
    2171                 :        122 : static int wps_process_e_hash1(struct wps_data *wps, const u8 *e_hash1)
    2172                 :            : {
    2173         [ -  + ]:        122 :         if (e_hash1 == NULL) {
    2174                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No E-Hash1 received");
    2175                 :          0 :                 return -1;
    2176                 :            :         }
    2177                 :            : 
    2178                 :        122 :         os_memcpy(wps->peer_hash1, e_hash1, WPS_HASH_LEN);
    2179                 :        122 :         wpa_hexdump(MSG_DEBUG, "WPS: E-Hash1", wps->peer_hash1, WPS_HASH_LEN);
    2180                 :            : 
    2181                 :        122 :         return 0;
    2182                 :            : }
    2183                 :            : 
    2184                 :            : 
    2185                 :        122 : static int wps_process_e_hash2(struct wps_data *wps, const u8 *e_hash2)
    2186                 :            : {
    2187         [ -  + ]:        122 :         if (e_hash2 == NULL) {
    2188                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No E-Hash2 received");
    2189                 :          0 :                 return -1;
    2190                 :            :         }
    2191                 :            : 
    2192                 :        122 :         os_memcpy(wps->peer_hash2, e_hash2, WPS_HASH_LEN);
    2193                 :        122 :         wpa_hexdump(MSG_DEBUG, "WPS: E-Hash2", wps->peer_hash2, WPS_HASH_LEN);
    2194                 :            : 
    2195                 :        122 :         return 0;
    2196                 :            : }
    2197                 :            : 
    2198                 :            : 
    2199                 :        116 : static int wps_process_e_snonce1(struct wps_data *wps, const u8 *e_snonce1)
    2200                 :            : {
    2201                 :            :         u8 hash[SHA256_MAC_LEN];
    2202                 :            :         const u8 *addr[4];
    2203                 :            :         size_t len[4];
    2204                 :            : 
    2205         [ -  + ]:        116 :         if (e_snonce1 == NULL) {
    2206                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No E-SNonce1 received");
    2207                 :          0 :                 return -1;
    2208                 :            :         }
    2209                 :            : 
    2210                 :        116 :         wpa_hexdump_key(MSG_DEBUG, "WPS: E-SNonce1", e_snonce1,
    2211                 :            :                         WPS_SECRET_NONCE_LEN);
    2212                 :            : 
    2213                 :            :         /* E-Hash1 = HMAC_AuthKey(E-S1 || PSK1 || PK_E || PK_R) */
    2214                 :        116 :         addr[0] = e_snonce1;
    2215                 :        116 :         len[0] = WPS_SECRET_NONCE_LEN;
    2216                 :        116 :         addr[1] = wps->psk1;
    2217                 :        116 :         len[1] = WPS_PSK_LEN;
    2218                 :        116 :         addr[2] = wpabuf_head(wps->dh_pubkey_e);
    2219                 :        116 :         len[2] = wpabuf_len(wps->dh_pubkey_e);
    2220                 :        116 :         addr[3] = wpabuf_head(wps->dh_pubkey_r);
    2221                 :        116 :         len[3] = wpabuf_len(wps->dh_pubkey_r);
    2222                 :        116 :         hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
    2223                 :            : 
    2224         [ -  + ]:        116 :         if (os_memcmp(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) {
    2225                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: E-Hash1 derived from E-S1 does "
    2226                 :            :                            "not match with the pre-committed value");
    2227                 :          0 :                 wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE;
    2228                 :          0 :                 wps_pwd_auth_fail_event(wps->wps, 0, 1, wps->mac_addr_e);
    2229                 :          0 :                 return -1;
    2230                 :            :         }
    2231                 :            : 
    2232                 :        116 :         wpa_printf(MSG_DEBUG, "WPS: Enrollee proved knowledge of the first "
    2233                 :            :                    "half of the device password");
    2234                 :            : 
    2235                 :        116 :         return 0;
    2236                 :            : }
    2237                 :            : 
    2238                 :            : 
    2239                 :        113 : static int wps_process_e_snonce2(struct wps_data *wps, const u8 *e_snonce2)
    2240                 :            : {
    2241                 :            :         u8 hash[SHA256_MAC_LEN];
    2242                 :            :         const u8 *addr[4];
    2243                 :            :         size_t len[4];
    2244                 :            : 
    2245         [ -  + ]:        113 :         if (e_snonce2 == NULL) {
    2246                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No E-SNonce2 received");
    2247                 :          0 :                 return -1;
    2248                 :            :         }
    2249                 :            : 
    2250                 :        113 :         wpa_hexdump_key(MSG_DEBUG, "WPS: E-SNonce2", e_snonce2,
    2251                 :            :                         WPS_SECRET_NONCE_LEN);
    2252                 :            : 
    2253                 :            :         /* E-Hash2 = HMAC_AuthKey(E-S2 || PSK2 || PK_E || PK_R) */
    2254                 :        113 :         addr[0] = e_snonce2;
    2255                 :        113 :         len[0] = WPS_SECRET_NONCE_LEN;
    2256                 :        113 :         addr[1] = wps->psk2;
    2257                 :        113 :         len[1] = WPS_PSK_LEN;
    2258                 :        113 :         addr[2] = wpabuf_head(wps->dh_pubkey_e);
    2259                 :        113 :         len[2] = wpabuf_len(wps->dh_pubkey_e);
    2260                 :        113 :         addr[3] = wpabuf_head(wps->dh_pubkey_r);
    2261                 :        113 :         len[3] = wpabuf_len(wps->dh_pubkey_r);
    2262                 :        113 :         hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
    2263                 :            : 
    2264         [ -  + ]:        113 :         if (os_memcmp(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) {
    2265                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: E-Hash2 derived from E-S2 does "
    2266                 :            :                            "not match with the pre-committed value");
    2267                 :          0 :                 wps_registrar_invalidate_pin(wps->wps->registrar, wps->uuid_e);
    2268                 :          0 :                 wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE;
    2269                 :          0 :                 wps_pwd_auth_fail_event(wps->wps, 0, 2, wps->mac_addr_e);
    2270                 :          0 :                 return -1;
    2271                 :            :         }
    2272                 :            : 
    2273                 :        113 :         wpa_printf(MSG_DEBUG, "WPS: Enrollee proved knowledge of the second "
    2274                 :            :                    "half of the device password");
    2275                 :        113 :         wps->wps_pin_revealed = 0;
    2276                 :        113 :         wps_registrar_unlock_pin(wps->wps->registrar, wps->uuid_e);
    2277                 :            : 
    2278                 :            :         /*
    2279                 :            :          * In case wildcard PIN is used and WPS handshake succeeds in the first
    2280                 :            :          * attempt, wps_registrar_unlock_pin() would not free the PIN, so make
    2281                 :            :          * sure the PIN gets invalidated here.
    2282                 :            :          */
    2283                 :        113 :         wps_registrar_invalidate_pin(wps->wps->registrar, wps->uuid_e);
    2284                 :            : 
    2285                 :        113 :         return 0;
    2286                 :            : }
    2287                 :            : 
    2288                 :            : 
    2289                 :        154 : static int wps_process_mac_addr(struct wps_data *wps, const u8 *mac_addr)
    2290                 :            : {
    2291         [ -  + ]:        154 :         if (mac_addr == NULL) {
    2292                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No MAC Address received");
    2293                 :          0 :                 return -1;
    2294                 :            :         }
    2295                 :            : 
    2296                 :        154 :         wpa_printf(MSG_DEBUG, "WPS: Enrollee MAC Address " MACSTR,
    2297                 :        924 :                    MAC2STR(mac_addr));
    2298                 :        154 :         os_memcpy(wps->mac_addr_e, mac_addr, ETH_ALEN);
    2299                 :        154 :         os_memcpy(wps->peer_dev.mac_addr, mac_addr, ETH_ALEN);
    2300                 :            : 
    2301                 :        154 :         return 0;
    2302                 :            : }
    2303                 :            : 
    2304                 :            : 
    2305                 :        154 : static int wps_process_pubkey(struct wps_data *wps, const u8 *pk,
    2306                 :            :                               size_t pk_len)
    2307                 :            : {
    2308 [ +  - ][ -  + ]:        154 :         if (pk == NULL || pk_len == 0) {
    2309                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No Public Key received");
    2310                 :          0 :                 return -1;
    2311                 :            :         }
    2312                 :            : 
    2313                 :        154 :         wpabuf_free(wps->dh_pubkey_e);
    2314                 :        154 :         wps->dh_pubkey_e = wpabuf_alloc_copy(pk, pk_len);
    2315         [ -  + ]:        154 :         if (wps->dh_pubkey_e == NULL)
    2316                 :          0 :                 return -1;
    2317                 :            : 
    2318                 :        154 :         return 0;
    2319                 :            : }
    2320                 :            : 
    2321                 :            : 
    2322                 :        154 : static int wps_process_auth_type_flags(struct wps_data *wps, const u8 *auth)
    2323                 :            : {
    2324                 :            :         u16 auth_types;
    2325                 :            : 
    2326         [ -  + ]:        154 :         if (auth == NULL) {
    2327                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No Authentication Type flags "
    2328                 :            :                            "received");
    2329                 :          0 :                 return -1;
    2330                 :            :         }
    2331                 :            : 
    2332                 :        154 :         auth_types = WPA_GET_BE16(auth);
    2333                 :            : 
    2334                 :        154 :         wpa_printf(MSG_DEBUG, "WPS: Enrollee Authentication Type flags 0x%x",
    2335                 :            :                    auth_types);
    2336                 :        154 :         wps->auth_type = wps->wps->auth_types & auth_types;
    2337         [ -  + ]:        154 :         if (wps->auth_type == 0) {
    2338                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No match in supported "
    2339                 :            :                            "authentication types (own 0x%x Enrollee 0x%x)",
    2340                 :          0 :                            wps->wps->auth_types, auth_types);
    2341                 :            : #ifdef WPS_WORKAROUNDS
    2342                 :            :                 /*
    2343                 :            :                  * Some deployed implementations seem to advertise incorrect
    2344                 :            :                  * information in this attribute. For example, Linksys WRT350N
    2345                 :            :                  * seems to have a byteorder bug that breaks this negotiation.
    2346                 :            :                  * In order to interoperate with existing implementations,
    2347                 :            :                  * assume that the Enrollee supports everything we do.
    2348                 :            :                  */
    2349                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Workaround - assume Enrollee "
    2350                 :            :                            "does not advertise supported authentication types "
    2351                 :            :                            "correctly");
    2352                 :          0 :                 wps->auth_type = wps->wps->auth_types;
    2353                 :            : #else /* WPS_WORKAROUNDS */
    2354                 :            :                 return -1;
    2355                 :            : #endif /* WPS_WORKAROUNDS */
    2356                 :            :         }
    2357                 :            : 
    2358                 :        154 :         return 0;
    2359                 :            : }
    2360                 :            : 
    2361                 :            : 
    2362                 :        154 : static int wps_process_encr_type_flags(struct wps_data *wps, const u8 *encr)
    2363                 :            : {
    2364                 :            :         u16 encr_types;
    2365                 :            : 
    2366         [ -  + ]:        154 :         if (encr == NULL) {
    2367                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No Encryption Type flags "
    2368                 :            :                            "received");
    2369                 :          0 :                 return -1;
    2370                 :            :         }
    2371                 :            : 
    2372                 :        154 :         encr_types = WPA_GET_BE16(encr);
    2373                 :            : 
    2374                 :        154 :         wpa_printf(MSG_DEBUG, "WPS: Enrollee Encryption Type flags 0x%x",
    2375                 :            :                    encr_types);
    2376                 :        154 :         wps->encr_type = wps->wps->encr_types & encr_types;
    2377         [ -  + ]:        154 :         if (wps->encr_type == 0) {
    2378                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No match in supported "
    2379                 :            :                            "encryption types (own 0x%x Enrollee 0x%x)",
    2380                 :          0 :                            wps->wps->encr_types, encr_types);
    2381                 :            : #ifdef WPS_WORKAROUNDS
    2382                 :            :                 /*
    2383                 :            :                  * Some deployed implementations seem to advertise incorrect
    2384                 :            :                  * information in this attribute. For example, Linksys WRT350N
    2385                 :            :                  * seems to have a byteorder bug that breaks this negotiation.
    2386                 :            :                  * In order to interoperate with existing implementations,
    2387                 :            :                  * assume that the Enrollee supports everything we do.
    2388                 :            :                  */
    2389                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Workaround - assume Enrollee "
    2390                 :            :                            "does not advertise supported encryption types "
    2391                 :            :                            "correctly");
    2392                 :          0 :                 wps->encr_type = wps->wps->encr_types;
    2393                 :            : #else /* WPS_WORKAROUNDS */
    2394                 :            :                 return -1;
    2395                 :            : #endif /* WPS_WORKAROUNDS */
    2396                 :            :         }
    2397                 :            : 
    2398                 :        154 :         return 0;
    2399                 :            : }
    2400                 :            : 
    2401                 :            : 
    2402                 :        154 : static int wps_process_conn_type_flags(struct wps_data *wps, const u8 *conn)
    2403                 :            : {
    2404         [ -  + ]:        154 :         if (conn == NULL) {
    2405                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No Connection Type flags "
    2406                 :            :                            "received");
    2407                 :          0 :                 return -1;
    2408                 :            :         }
    2409                 :            : 
    2410                 :        154 :         wpa_printf(MSG_DEBUG, "WPS: Enrollee Connection Type flags 0x%x",
    2411                 :        154 :                    *conn);
    2412                 :            : 
    2413                 :        154 :         return 0;
    2414                 :            : }
    2415                 :            : 
    2416                 :            : 
    2417                 :        154 : static int wps_process_config_methods(struct wps_data *wps, const u8 *methods)
    2418                 :            : {
    2419                 :            :         u16 m;
    2420                 :            : 
    2421         [ -  + ]:        154 :         if (methods == NULL) {
    2422                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No Config Methods received");
    2423                 :          0 :                 return -1;
    2424                 :            :         }
    2425                 :            : 
    2426                 :        154 :         m = WPA_GET_BE16(methods);
    2427                 :            : 
    2428 [ +  + ][ +  + ]:        154 :         wpa_printf(MSG_DEBUG, "WPS: Enrollee Config Methods 0x%x"
         [ -  + ][ -  + ]
         [ +  + ][ +  + ]
         [ -  + ][ -  + ]
                 [ +  + ]
    2429                 :            :                    "%s%s%s%s%s%s%s%s%s", m,
    2430                 :        154 :                    m & WPS_CONFIG_USBA ? " [USBA]" : "",
    2431                 :        154 :                    m & WPS_CONFIG_ETHERNET ? " [Ethernet]" : "",
    2432                 :        154 :                    m & WPS_CONFIG_LABEL ? " [Label]" : "",
    2433                 :        154 :                    m & WPS_CONFIG_DISPLAY ? " [Display]" : "",
    2434                 :        154 :                    m & WPS_CONFIG_EXT_NFC_TOKEN ? " [Ext NFC Token]" : "",
    2435                 :        154 :                    m & WPS_CONFIG_INT_NFC_TOKEN ? " [Int NFC Token]" : "",
    2436                 :        154 :                    m & WPS_CONFIG_NFC_INTERFACE ? " [NFC]" : "",
    2437                 :        154 :                    m & WPS_CONFIG_PUSHBUTTON ? " [PBC]" : "",
    2438                 :        154 :                    m & WPS_CONFIG_KEYPAD ? " [Keypad]" : "");
    2439                 :            : 
    2440 [ +  - ][ +  + ]:        154 :         if (!(m & WPS_CONFIG_DISPLAY) && !wps->use_psk_key) {
    2441                 :            :                 /*
    2442                 :            :                  * The Enrollee does not have a display so it is unlikely to be
    2443                 :            :                  * able to show the passphrase to a user and as such, could
    2444                 :            :                  * benefit from receiving PSK to reduce key derivation time.
    2445                 :            :                  */
    2446                 :         15 :                 wpa_printf(MSG_DEBUG, "WPS: Prefer PSK format key due to "
    2447                 :            :                            "Enrollee not supporting display");
    2448                 :         15 :                 wps->use_psk_key = 1;
    2449                 :            :         }
    2450                 :            : 
    2451                 :        154 :         return 0;
    2452                 :            : }
    2453                 :            : 
    2454                 :            : 
    2455                 :        154 : static int wps_process_wps_state(struct wps_data *wps, const u8 *state)
    2456                 :            : {
    2457         [ -  + ]:        154 :         if (state == NULL) {
    2458                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No Wi-Fi Protected Setup State "
    2459                 :            :                            "received");
    2460                 :          0 :                 return -1;
    2461                 :            :         }
    2462                 :            : 
    2463                 :        154 :         wpa_printf(MSG_DEBUG, "WPS: Enrollee Wi-Fi Protected Setup State %d",
    2464                 :        154 :                    *state);
    2465                 :            : 
    2466                 :        154 :         return 0;
    2467                 :            : }
    2468                 :            : 
    2469                 :            : 
    2470                 :        154 : static int wps_process_assoc_state(struct wps_data *wps, const u8 *assoc)
    2471                 :            : {
    2472                 :            :         u16 a;
    2473                 :            : 
    2474         [ -  + ]:        154 :         if (assoc == NULL) {
    2475                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No Association State received");
    2476                 :          0 :                 return -1;
    2477                 :            :         }
    2478                 :            : 
    2479                 :        154 :         a = WPA_GET_BE16(assoc);
    2480                 :        154 :         wpa_printf(MSG_DEBUG, "WPS: Enrollee Association State %d", a);
    2481                 :            : 
    2482                 :        154 :         return 0;
    2483                 :            : }
    2484                 :            : 
    2485                 :            : 
    2486                 :        154 : static int wps_process_config_error(struct wps_data *wps, const u8 *err)
    2487                 :            : {
    2488                 :            :         u16 e;
    2489                 :            : 
    2490         [ -  + ]:        154 :         if (err == NULL) {
    2491                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No Configuration Error received");
    2492                 :          0 :                 return -1;
    2493                 :            :         }
    2494                 :            : 
    2495                 :        154 :         e = WPA_GET_BE16(err);
    2496                 :        154 :         wpa_printf(MSG_DEBUG, "WPS: Enrollee Configuration Error %d", e);
    2497                 :            : 
    2498                 :        154 :         return 0;
    2499                 :            : }
    2500                 :            : 
    2501                 :            : 
    2502                 :         15 : static int wps_registrar_p2p_dev_addr_match(struct wps_data *wps)
    2503                 :            : {
    2504                 :            : #ifdef CONFIG_P2P
    2505                 :          6 :         struct wps_registrar *reg = wps->wps->registrar;
    2506                 :            : 
    2507         [ +  + ]:          6 :         if (is_zero_ether_addr(reg->p2p_dev_addr))
    2508                 :          3 :                 return 1; /* no filtering in use */
    2509                 :            : 
    2510         [ -  + ]:          3 :         if (os_memcmp(reg->p2p_dev_addr, wps->p2p_dev_addr, ETH_ALEN) != 0) {
    2511                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No match on P2P Device Address "
    2512                 :            :                            "filtering for PBC: expected " MACSTR " was "
    2513                 :            :                            MACSTR " - indicate PBC session overlap",
    2514                 :          0 :                            MAC2STR(reg->p2p_dev_addr),
    2515                 :          0 :                            MAC2STR(wps->p2p_dev_addr));
    2516                 :          0 :                 return 0;
    2517                 :            :         }
    2518                 :            : #endif /* CONFIG_P2P */
    2519                 :         15 :         return 1;
    2520                 :            : }
    2521                 :            : 
    2522                 :            : 
    2523                 :          2 : static int wps_registrar_skip_overlap(struct wps_data *wps)
    2524                 :            : {
    2525                 :            : #ifdef CONFIG_P2P
    2526                 :          0 :         struct wps_registrar *reg = wps->wps->registrar;
    2527                 :            : 
    2528         [ #  # ]:          0 :         if (is_zero_ether_addr(reg->p2p_dev_addr))
    2529                 :          0 :                 return 0; /* no specific Enrollee selected */
    2530                 :            : 
    2531         [ #  # ]:          0 :         if (os_memcmp(reg->p2p_dev_addr, wps->p2p_dev_addr, ETH_ALEN) == 0) {
    2532                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Skip PBC overlap due to selected "
    2533                 :            :                            "Enrollee match");
    2534                 :          0 :                 return 1;
    2535                 :            :         }
    2536                 :            : #endif /* CONFIG_P2P */
    2537                 :          2 :         return 0;
    2538                 :            : }
    2539                 :            : 
    2540                 :            : 
    2541                 :        154 : static enum wps_process_res wps_process_m1(struct wps_data *wps,
    2542                 :            :                                            struct wps_parse_attr *attr)
    2543                 :            : {
    2544                 :        154 :         wpa_printf(MSG_DEBUG, "WPS: Received M1");
    2545                 :            : 
    2546         [ -  + ]:        154 :         if (wps->state != RECV_M1) {
    2547                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
    2548                 :          0 :                            "receiving M1", wps->state);
    2549                 :          0 :                 return WPS_FAILURE;
    2550                 :            :         }
    2551                 :            : 
    2552   [ +  -  +  - ]:        308 :         if (wps_process_uuid_e(wps, attr->uuid_e) ||
    2553         [ +  - ]:        308 :             wps_process_mac_addr(wps, attr->mac_addr) ||
    2554         [ +  - ]:        308 :             wps_process_enrollee_nonce(wps, attr->enrollee_nonce) ||
    2555         [ +  - ]:        308 :             wps_process_pubkey(wps, attr->public_key, attr->public_key_len) ||
    2556         [ +  - ]:        308 :             wps_process_auth_type_flags(wps, attr->auth_type_flags) ||
    2557         [ +  - ]:        308 :             wps_process_encr_type_flags(wps, attr->encr_type_flags) ||
    2558         [ +  - ]:        308 :             wps_process_conn_type_flags(wps, attr->conn_type_flags) ||
    2559         [ +  - ]:        308 :             wps_process_config_methods(wps, attr->config_methods) ||
    2560         [ +  - ]:        308 :             wps_process_wps_state(wps, attr->wps_state) ||
    2561         [ +  - ]:        308 :             wps_process_device_attrs(&wps->peer_dev, attr) ||
    2562         [ +  - ]:        308 :             wps_process_rf_bands(&wps->peer_dev, attr->rf_bands) ||
    2563         [ +  - ]:        308 :             wps_process_assoc_state(wps, attr->assoc_state) ||
    2564         [ +  - ]:        308 :             wps_process_dev_password_id(wps, attr->dev_password_id) ||
    2565         [ -  + ]:        308 :             wps_process_config_error(wps, attr->config_error) ||
    2566                 :        154 :             wps_process_os_version(&wps->peer_dev, attr->os_version))
    2567                 :          0 :                 return WPS_FAILURE;
    2568                 :            : 
    2569 [ +  + ][ +  + ]:        154 :         if (wps->dev_pw_id < 0x10 &&
    2570         [ +  - ]:         72 :             wps->dev_pw_id != DEV_PW_DEFAULT &&
    2571         [ +  - ]:         72 :             wps->dev_pw_id != DEV_PW_USER_SPECIFIED &&
    2572         [ +  + ]:         72 :             wps->dev_pw_id != DEV_PW_MACHINE_SPECIFIED &&
    2573         [ +  + ]:         36 :             wps->dev_pw_id != DEV_PW_REGISTRAR_SPECIFIED &&
    2574                 :            : #ifdef CONFIG_WPS_NFC
    2575         [ +  - ]:         18 :             wps->dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER &&
    2576                 :            : #endif /* CONFIG_WPS_NFC */
    2577         [ +  + ]:         18 :             (wps->dev_pw_id != DEV_PW_PUSHBUTTON ||
    2578                 :         18 :              !wps->wps->registrar->pbc)) {
    2579                 :          1 :                 wpa_printf(MSG_DEBUG, "WPS: Unsupported Device Password ID %d",
    2580                 :          1 :                            wps->dev_pw_id);
    2581                 :          1 :                 wps->state = SEND_M2D;
    2582                 :          1 :                 return WPS_CONTINUE;
    2583                 :            :         }
    2584                 :            : 
    2585                 :            : #ifdef CONFIG_WPS_NFC
    2586 [ +  + ][ +  + ]:        153 :         if (wps->dev_pw_id >= 0x10 ||
    2587                 :        142 :             wps->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) {
    2588                 :            :                 struct wps_nfc_pw_token *token;
    2589                 :            :                 const u8 *addr[1];
    2590                 :            :                 u8 hash[WPS_HASH_LEN];
    2591                 :            : 
    2592                 :         29 :                 wpa_printf(MSG_DEBUG, "WPS: Searching for NFC token match for id=%d (ctx %p registrar %p)",
    2593                 :         58 :                            wps->dev_pw_id, wps->wps, wps->wps->registrar);
    2594                 :         29 :                 token = wps_get_nfc_pw_token(
    2595                 :         58 :                         &wps->wps->registrar->nfc_pw_tokens, wps->dev_pw_id);
    2596 [ +  + ][ +  + ]:         29 :                 if (token && token->peer_pk_hash_known) {
    2597                 :         22 :                         wpa_printf(MSG_DEBUG, "WPS: Found matching NFC "
    2598                 :            :                                    "Password Token");
    2599                 :         22 :                         dl_list_del(&token->list);
    2600                 :         22 :                         wps->nfc_pw_token = token;
    2601                 :            : 
    2602                 :         22 :                         addr[0] = attr->public_key;
    2603                 :         22 :                         sha256_vector(1, addr, &attr->public_key_len, hash);
    2604         [ +  + ]:         22 :                         if (os_memcmp(hash, wps->nfc_pw_token->pubkey_hash,
    2605                 :            :                                       WPS_OOB_PUBKEY_HASH_LEN) != 0) {
    2606                 :          2 :                                 wpa_printf(MSG_ERROR, "WPS: Public Key hash "
    2607                 :            :                                            "mismatch");
    2608                 :          2 :                                 wps->state = SEND_M2D;
    2609                 :          2 :                                 wps->config_error =
    2610                 :            :                                         WPS_CFG_PUBLIC_KEY_HASH_MISMATCH;
    2611                 :          2 :                                 return WPS_CONTINUE;
    2612                 :            :                         }
    2613         [ +  + ]:          7 :                 } else if (token) {
    2614                 :          1 :                         wpa_printf(MSG_DEBUG, "WPS: Found matching NFC "
    2615                 :            :                                    "Password Token (no peer PK hash)");
    2616                 :          1 :                         wps->nfc_pw_token = token;
    2617 [ +  + ][ +  + ]:          6 :                 } else if (wps->dev_pw_id >= 0x10 &&
    2618         [ +  - ]:          2 :                            wps->wps->ap_nfc_dev_pw_id == wps->dev_pw_id &&
    2619                 :          2 :                            wps->wps->ap_nfc_dev_pw) {
    2620                 :          2 :                         wpa_printf(MSG_DEBUG, "WPS: Found match with own NFC Password Token");
    2621                 :            :                 }
    2622                 :            :         }
    2623                 :            : #endif /* CONFIG_WPS_NFC */
    2624                 :            : 
    2625         [ +  + ]:        151 :         if (wps->dev_pw_id == DEV_PW_PUSHBUTTON) {
    2626   [ +  +  +  - ]:         32 :                 if ((wps->wps->registrar->force_pbc_overlap ||
    2627                 :         15 :                      wps_registrar_pbc_overlap(wps->wps->registrar,
    2628         [ -  + ]:         15 :                                                wps->mac_addr_e, wps->uuid_e) ||
    2629         [ +  - ]:         17 :                      !wps_registrar_p2p_dev_addr_match(wps)) &&
    2630                 :          2 :                     !wps_registrar_skip_overlap(wps)) {
    2631                 :          2 :                         wpa_printf(MSG_DEBUG, "WPS: PBC overlap - deny PBC "
    2632                 :            :                                    "negotiation");
    2633                 :          2 :                         wps->state = SEND_M2D;
    2634                 :          2 :                         wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED;
    2635                 :          2 :                         wps_pbc_overlap_event(wps->wps);
    2636                 :          2 :                         wps_fail_event(wps->wps, WPS_M1,
    2637                 :            :                                        WPS_CFG_MULTIPLE_PBC_DETECTED,
    2638                 :          2 :                                        WPS_EI_NO_ERROR, wps->mac_addr_e);
    2639                 :          2 :                         wps->wps->registrar->force_pbc_overlap = 1;
    2640                 :          2 :                         return WPS_CONTINUE;
    2641                 :            :                 }
    2642                 :         15 :                 wps_registrar_add_pbc_session(wps->wps->registrar,
    2643                 :         15 :                                               wps->mac_addr_e, wps->uuid_e);
    2644                 :         15 :                 wps->pbc = 1;
    2645                 :            :         }
    2646                 :            : 
    2647                 :            : #ifdef WPS_WORKAROUNDS
    2648                 :            :         /*
    2649                 :            :          * It looks like Mac OS X 10.6.3 and 10.6.4 do not like Network Key in
    2650                 :            :          * passphrase format. To avoid interop issues, force PSK format to be
    2651                 :            :          * used.
    2652                 :            :          */
    2653 [ +  + ][ +  - ]:        149 :         if (!wps->use_psk_key &&
    2654         [ -  + ]:         55 :             wps->peer_dev.manufacturer &&
    2655         [ #  # ]:          0 :             os_strncmp(wps->peer_dev.manufacturer, "Apple ", 6) == 0 &&
    2656         [ #  # ]:          0 :             wps->peer_dev.model_name &&
    2657                 :          0 :             os_strcmp(wps->peer_dev.model_name, "AirPort") == 0) {
    2658                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Workaround - Force Network Key in "
    2659                 :            :                            "PSK format");
    2660                 :          0 :                 wps->use_psk_key = 1;
    2661                 :            :         }
    2662                 :            : #endif /* WPS_WORKAROUNDS */
    2663                 :            : 
    2664                 :        149 :         wps->state = SEND_M2;
    2665                 :        154 :         return WPS_CONTINUE;
    2666                 :            : }
    2667                 :            : 
    2668                 :            : 
    2669                 :        122 : static enum wps_process_res wps_process_m3(struct wps_data *wps,
    2670                 :            :                                            const struct wpabuf *msg,
    2671                 :            :                                            struct wps_parse_attr *attr)
    2672                 :            : {
    2673                 :        122 :         wpa_printf(MSG_DEBUG, "WPS: Received M3");
    2674                 :            : 
    2675         [ -  + ]:        122 :         if (wps->state != RECV_M3) {
    2676                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
    2677                 :          0 :                            "receiving M3", wps->state);
    2678                 :          0 :                 wps->state = SEND_WSC_NACK;
    2679                 :          0 :                 return WPS_CONTINUE;
    2680                 :            :         }
    2681                 :            : 
    2682         [ +  + ]:        122 :         if (wps->pbc && wps->wps->registrar->force_pbc_overlap &&
           [ -  +  #  # ]
    2683                 :          0 :             !wps_registrar_skip_overlap(wps)) {
    2684                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Reject negotiation due to PBC "
    2685                 :            :                            "session overlap");
    2686                 :          0 :                 wps->state = SEND_WSC_NACK;
    2687                 :          0 :                 wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED;
    2688                 :          0 :                 return WPS_CONTINUE;
    2689                 :            :         }
    2690                 :            : 
    2691   [ +  -  +  - ]:        244 :         if (wps_process_registrar_nonce(wps, attr->registrar_nonce) ||
    2692         [ +  - ]:        244 :             wps_process_authenticator(wps, attr->authenticator, msg) ||
    2693         [ -  + ]:        244 :             wps_process_e_hash1(wps, attr->e_hash1) ||
    2694                 :        122 :             wps_process_e_hash2(wps, attr->e_hash2)) {
    2695                 :          0 :                 wps->state = SEND_WSC_NACK;
    2696                 :          0 :                 return WPS_CONTINUE;
    2697                 :            :         }
    2698                 :            : 
    2699                 :        122 :         wps->state = SEND_M4;
    2700                 :        122 :         return WPS_CONTINUE;
    2701                 :            : }
    2702                 :            : 
    2703                 :            : 
    2704                 :        116 : static enum wps_process_res wps_process_m5(struct wps_data *wps,
    2705                 :            :                                            const struct wpabuf *msg,
    2706                 :            :                                            struct wps_parse_attr *attr)
    2707                 :            : {
    2708                 :            :         struct wpabuf *decrypted;
    2709                 :            :         struct wps_parse_attr eattr;
    2710                 :            : 
    2711                 :        116 :         wpa_printf(MSG_DEBUG, "WPS: Received M5");
    2712                 :            : 
    2713         [ -  + ]:        116 :         if (wps->state != RECV_M5) {
    2714                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
    2715                 :          0 :                            "receiving M5", wps->state);
    2716                 :          0 :                 wps->state = SEND_WSC_NACK;
    2717                 :          0 :                 return WPS_CONTINUE;
    2718                 :            :         }
    2719                 :            : 
    2720         [ +  + ]:        116 :         if (wps->pbc && wps->wps->registrar->force_pbc_overlap &&
           [ -  +  #  # ]
    2721                 :          0 :             !wps_registrar_skip_overlap(wps)) {
    2722                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Reject negotiation due to PBC "
    2723                 :            :                            "session overlap");
    2724                 :          0 :                 wps->state = SEND_WSC_NACK;
    2725                 :          0 :                 wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED;
    2726                 :          0 :                 return WPS_CONTINUE;
    2727                 :            :         }
    2728                 :            : 
    2729   [ +  -  -  + ]:        232 :         if (wps_process_registrar_nonce(wps, attr->registrar_nonce) ||
    2730                 :        116 :             wps_process_authenticator(wps, attr->authenticator, msg)) {
    2731                 :          0 :                 wps->state = SEND_WSC_NACK;
    2732                 :          0 :                 return WPS_CONTINUE;
    2733                 :            :         }
    2734                 :            : 
    2735                 :        116 :         decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings,
    2736                 :            :                                               attr->encr_settings_len);
    2737         [ -  + ]:        116 :         if (decrypted == NULL) {
    2738                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted "
    2739                 :            :                            "Settings attribute");
    2740                 :          0 :                 wps->state = SEND_WSC_NACK;
    2741                 :          0 :                 return WPS_CONTINUE;
    2742                 :            :         }
    2743                 :            : 
    2744         [ -  + ]:        116 :         if (wps_validate_m5_encr(decrypted, attr->version2 != NULL) < 0) {
    2745                 :          0 :                 wpabuf_free(decrypted);
    2746                 :          0 :                 wps->state = SEND_WSC_NACK;
    2747                 :          0 :                 return WPS_CONTINUE;
    2748                 :            :         }
    2749                 :            : 
    2750                 :        116 :         wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings "
    2751                 :            :                    "attribute");
    2752   [ +  -  +  - ]:        232 :         if (wps_parse_msg(decrypted, &eattr) < 0 ||
    2753         [ -  + ]:        232 :             wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
    2754                 :        116 :             wps_process_e_snonce1(wps, eattr.e_snonce1)) {
    2755                 :          0 :                 wpabuf_free(decrypted);
    2756                 :          0 :                 wps->state = SEND_WSC_NACK;
    2757                 :          0 :                 return WPS_CONTINUE;
    2758                 :            :         }
    2759                 :        116 :         wpabuf_free(decrypted);
    2760                 :            : 
    2761                 :        116 :         wps->state = SEND_M6;
    2762                 :        116 :         return WPS_CONTINUE;
    2763                 :            : }
    2764                 :            : 
    2765                 :            : 
    2766                 :         16 : static void wps_sta_cred_cb(struct wps_data *wps)
    2767                 :            : {
    2768                 :            :         /*
    2769                 :            :          * Update credential to only include a single authentication and
    2770                 :            :          * encryption type in case the AP configuration includes more than one
    2771                 :            :          * option.
    2772                 :            :          */
    2773         [ +  + ]:         16 :         if (wps->cred.auth_type & WPS_AUTH_WPA2PSK)
    2774                 :         15 :                 wps->cred.auth_type = WPS_AUTH_WPA2PSK;
    2775         [ +  - ]:          1 :         else if (wps->cred.auth_type & WPS_AUTH_WPAPSK)
    2776                 :          1 :                 wps->cred.auth_type = WPS_AUTH_WPAPSK;
    2777         [ +  + ]:         16 :         if (wps->cred.encr_type & WPS_ENCR_AES)
    2778                 :         15 :                 wps->cred.encr_type = WPS_ENCR_AES;
    2779         [ +  - ]:          1 :         else if (wps->cred.encr_type & WPS_ENCR_TKIP)
    2780                 :          1 :                 wps->cred.encr_type = WPS_ENCR_TKIP;
    2781                 :         16 :         wpa_printf(MSG_DEBUG, "WPS: Update local configuration based on the "
    2782                 :            :                    "AP configuration");
    2783         [ +  - ]:         16 :         if (wps->wps->cred_cb)
    2784                 :         16 :                 wps->wps->cred_cb(wps->wps->cb_ctx, &wps->cred);
    2785                 :         16 : }
    2786                 :            : 
    2787                 :            : 
    2788                 :          6 : static void wps_cred_update(struct wps_credential *dst,
    2789                 :            :                             struct wps_credential *src)
    2790                 :            : {
    2791                 :          6 :         os_memcpy(dst->ssid, src->ssid, sizeof(dst->ssid));
    2792                 :          6 :         dst->ssid_len = src->ssid_len;
    2793                 :          6 :         dst->auth_type = src->auth_type;
    2794                 :          6 :         dst->encr_type = src->encr_type;
    2795                 :          6 :         dst->key_idx = src->key_idx;
    2796                 :          6 :         os_memcpy(dst->key, src->key, sizeof(dst->key));
    2797                 :          6 :         dst->key_len = src->key_len;
    2798                 :          6 : }
    2799                 :            : 
    2800                 :            : 
    2801                 :        113 : static int wps_process_ap_settings_r(struct wps_data *wps,
    2802                 :            :                                      struct wps_parse_attr *attr)
    2803                 :            : {
    2804                 :            :         struct wpabuf *msg;
    2805                 :            : 
    2806 [ +  + ][ +  + ]:        113 :         if (wps->wps->ap || wps->er)
    2807                 :         95 :                 return 0;
    2808                 :            : 
    2809                 :            :         /* AP Settings Attributes in M7 when Enrollee is an AP */
    2810         [ -  + ]:         18 :         if (wps_process_ap_settings(attr, &wps->cred) < 0)
    2811                 :          0 :                 return -1;
    2812                 :            : 
    2813                 :         18 :         wpa_printf(MSG_INFO, "WPS: Received old AP configuration from AP");
    2814                 :            : 
    2815         [ +  + ]:         18 :         if (wps->new_ap_settings) {
    2816                 :          6 :                 wpa_printf(MSG_INFO, "WPS: Update AP configuration based on "
    2817                 :            :                            "new settings");
    2818                 :          6 :                 wps_cred_update(&wps->cred, wps->new_ap_settings);
    2819                 :          6 :                 return 0;
    2820                 :            :         } else {
    2821                 :            :                 /*
    2822                 :            :                  * Use the AP PIN only to receive the current AP settings, not
    2823                 :            :                  * to reconfigure the AP.
    2824                 :            :                  */
    2825                 :            : 
    2826                 :            :                 /*
    2827                 :            :                  * Clear selected registrar here since we do not get to
    2828                 :            :                  * WSC_Done in this protocol run.
    2829                 :            :                  */
    2830                 :         12 :                 wps_registrar_pin_completed(wps->wps->registrar);
    2831                 :            : 
    2832                 :         12 :                 msg = wps_build_ap_cred(wps);
    2833         [ -  + ]:         12 :                 if (msg == NULL)
    2834                 :          0 :                         return -1;
    2835                 :         12 :                 wps->cred.cred_attr = wpabuf_head(msg);
    2836                 :         12 :                 wps->cred.cred_attr_len = wpabuf_len(msg);
    2837                 :            : 
    2838         [ +  + ]:         12 :                 if (wps->ap_settings_cb) {
    2839                 :          1 :                         wps->ap_settings_cb(wps->ap_settings_cb_ctx,
    2840                 :          1 :                                             &wps->cred);
    2841                 :          1 :                         wpabuf_free(msg);
    2842                 :          1 :                         return 1;
    2843                 :            :                 }
    2844                 :         11 :                 wps_sta_cred_cb(wps);
    2845                 :            : 
    2846                 :         11 :                 wps->cred.cred_attr = NULL;
    2847                 :         11 :                 wps->cred.cred_attr_len = 0;
    2848                 :         11 :                 wpabuf_free(msg);
    2849                 :            : 
    2850                 :        113 :                 return 1;
    2851                 :            :         }
    2852                 :            : }
    2853                 :            : 
    2854                 :            : 
    2855                 :        113 : static enum wps_process_res wps_process_m7(struct wps_data *wps,
    2856                 :            :                                            const struct wpabuf *msg,
    2857                 :            :                                            struct wps_parse_attr *attr)
    2858                 :            : {
    2859                 :            :         struct wpabuf *decrypted;
    2860                 :            :         struct wps_parse_attr eattr;
    2861                 :            : 
    2862                 :        113 :         wpa_printf(MSG_DEBUG, "WPS: Received M7");
    2863                 :            : 
    2864         [ -  + ]:        113 :         if (wps->state != RECV_M7) {
    2865                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
    2866                 :          0 :                            "receiving M7", wps->state);
    2867                 :          0 :                 wps->state = SEND_WSC_NACK;
    2868                 :          0 :                 return WPS_CONTINUE;
    2869                 :            :         }
    2870                 :            : 
    2871         [ +  + ]:        113 :         if (wps->pbc && wps->wps->registrar->force_pbc_overlap &&
           [ -  +  #  # ]
    2872                 :          0 :             !wps_registrar_skip_overlap(wps)) {
    2873                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Reject negotiation due to PBC "
    2874                 :            :                            "session overlap");
    2875                 :          0 :                 wps->state = SEND_WSC_NACK;
    2876                 :          0 :                 wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED;
    2877                 :          0 :                 return WPS_CONTINUE;
    2878                 :            :         }
    2879                 :            : 
    2880   [ +  -  -  + ]:        226 :         if (wps_process_registrar_nonce(wps, attr->registrar_nonce) ||
    2881                 :        113 :             wps_process_authenticator(wps, attr->authenticator, msg)) {
    2882                 :          0 :                 wps->state = SEND_WSC_NACK;
    2883                 :          0 :                 return WPS_CONTINUE;
    2884                 :            :         }
    2885                 :            : 
    2886                 :        113 :         decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings,
    2887                 :            :                                               attr->encr_settings_len);
    2888         [ -  + ]:        113 :         if (decrypted == NULL) {
    2889                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Failed to decrypt Encrypted "
    2890                 :            :                            "Settings attribute");
    2891                 :          0 :                 wps->state = SEND_WSC_NACK;
    2892                 :          0 :                 return WPS_CONTINUE;
    2893                 :            :         }
    2894                 :            : 
    2895 [ +  + ][ +  + ]:        113 :         if (wps_validate_m7_encr(decrypted, wps->wps->ap || wps->er,
                 [ -  + ]
    2896                 :        113 :                                  attr->version2 != NULL) < 0) {
    2897                 :          0 :                 wpabuf_free(decrypted);
    2898                 :          0 :                 wps->state = SEND_WSC_NACK;
    2899                 :          0 :                 return WPS_CONTINUE;
    2900                 :            :         }
    2901                 :            : 
    2902                 :        113 :         wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings "
    2903                 :            :                    "attribute");
    2904   [ +  -  +  - ]:        226 :         if (wps_parse_msg(decrypted, &eattr) < 0 ||
    2905         [ +  - ]:        226 :             wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
    2906         [ +  + ]:        226 :             wps_process_e_snonce2(wps, eattr.e_snonce2) ||
    2907                 :        113 :             wps_process_ap_settings_r(wps, &eattr)) {
    2908                 :         12 :                 wpabuf_free(decrypted);
    2909                 :         12 :                 wps->state = SEND_WSC_NACK;
    2910                 :         12 :                 return WPS_CONTINUE;
    2911                 :            :         }
    2912                 :            : 
    2913                 :        101 :         wpabuf_free(decrypted);
    2914                 :            : 
    2915                 :        101 :         wps->state = SEND_M8;
    2916                 :        113 :         return WPS_CONTINUE;
    2917                 :            : }
    2918                 :            : 
    2919                 :            : 
    2920                 :        505 : static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps,
    2921                 :            :                                                 const struct wpabuf *msg)
    2922                 :            : {
    2923                 :            :         struct wps_parse_attr attr;
    2924                 :        505 :         enum wps_process_res ret = WPS_CONTINUE;
    2925                 :            : 
    2926                 :        505 :         wpa_printf(MSG_DEBUG, "WPS: Received WSC_MSG");
    2927                 :            : 
    2928         [ -  + ]:        505 :         if (wps_parse_msg(msg, &attr) < 0)
    2929                 :          0 :                 return WPS_FAILURE;
    2930                 :            : 
    2931         [ -  + ]:        505 :         if (attr.msg_type == NULL) {
    2932                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
    2933                 :          0 :                 wps->state = SEND_WSC_NACK;
    2934                 :          0 :                 return WPS_CONTINUE;
    2935                 :            :         }
    2936                 :            : 
    2937 [ +  + ][ +  - ]:        505 :         if (*attr.msg_type != WPS_M1 &&
    2938         [ -  + ]:        351 :             (attr.registrar_nonce == NULL ||
    2939                 :        351 :              os_memcmp(wps->nonce_r, attr.registrar_nonce,
    2940                 :            :                        WPS_NONCE_LEN) != 0)) {
    2941                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce");
    2942                 :          0 :                 return WPS_FAILURE;
    2943                 :            :         }
    2944                 :            : 
    2945   [ +  +  +  +  :        505 :         switch (*attr.msg_type) {
                      - ]
    2946                 :            :         case WPS_M1:
    2947         [ -  + ]:        154 :                 if (wps_validate_m1(msg) < 0)
    2948                 :          0 :                         return WPS_FAILURE;
    2949                 :            : #ifdef CONFIG_WPS_UPNP
    2950 [ +  + ][ +  - ]:        154 :                 if (wps->wps->wps_upnp && attr.mac_addr) {
    2951                 :            :                         /* Remove old pending messages when starting new run */
    2952                 :          8 :                         wps_free_pending_msgs(wps->wps->upnp_msgs);
    2953                 :          8 :                         wps->wps->upnp_msgs = NULL;
    2954                 :            : 
    2955                 :          8 :                         upnp_wps_device_send_wlan_event(
    2956                 :          8 :                                 wps->wps->wps_upnp, attr.mac_addr,
    2957                 :            :                                 UPNP_WPS_WLANEVENT_TYPE_EAP, msg);
    2958                 :            :                 }
    2959                 :            : #endif /* CONFIG_WPS_UPNP */
    2960                 :        154 :                 ret = wps_process_m1(wps, &attr);
    2961                 :        154 :                 break;
    2962                 :            :         case WPS_M3:
    2963         [ -  + ]:        122 :                 if (wps_validate_m3(msg) < 0)
    2964                 :          0 :                         return WPS_FAILURE;
    2965                 :        122 :                 ret = wps_process_m3(wps, msg, &attr);
    2966 [ -  + ][ +  - ]:        122 :                 if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
    2967                 :          0 :                         wps_fail_event(wps->wps, WPS_M3, wps->config_error,
    2968                 :          0 :                                        wps->error_indication, wps->mac_addr_e);
    2969                 :        122 :                 break;
    2970                 :            :         case WPS_M5:
    2971         [ -  + ]:        116 :                 if (wps_validate_m5(msg) < 0)
    2972                 :          0 :                         return WPS_FAILURE;
    2973                 :        116 :                 ret = wps_process_m5(wps, msg, &attr);
    2974 [ -  + ][ +  - ]:        116 :                 if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
    2975                 :          0 :                         wps_fail_event(wps->wps, WPS_M5, wps->config_error,
    2976                 :          0 :                                        wps->error_indication, wps->mac_addr_e);
    2977                 :        116 :                 break;
    2978                 :            :         case WPS_M7:
    2979         [ -  + ]:        113 :                 if (wps_validate_m7(msg) < 0)
    2980                 :          0 :                         return WPS_FAILURE;
    2981                 :        113 :                 ret = wps_process_m7(wps, msg, &attr);
    2982 [ +  + ][ +  - ]:        113 :                 if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
    2983                 :         12 :                         wps_fail_event(wps->wps, WPS_M7, wps->config_error,
    2984                 :         12 :                                        wps->error_indication, wps->mac_addr_e);
    2985                 :        113 :                 break;
    2986                 :            :         default:
    2987                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Unsupported Message Type %d",
    2988                 :          0 :                            *attr.msg_type);
    2989                 :          0 :                 return WPS_FAILURE;
    2990                 :            :         }
    2991                 :            : 
    2992         [ +  - ]:        505 :         if (ret == WPS_CONTINUE) {
    2993                 :            :                 /* Save a copy of the last message for Authenticator derivation
    2994                 :            :                  */
    2995                 :        505 :                 wpabuf_free(wps->last_msg);
    2996                 :        505 :                 wps->last_msg = wpabuf_dup(msg);
    2997                 :            :         }
    2998                 :            : 
    2999                 :        505 :         return ret;
    3000                 :            : }
    3001                 :            : 
    3002                 :            : 
    3003                 :         21 : static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps,
    3004                 :            :                                                 const struct wpabuf *msg)
    3005                 :            : {
    3006                 :            :         struct wps_parse_attr attr;
    3007                 :            : 
    3008                 :         21 :         wpa_printf(MSG_DEBUG, "WPS: Received WSC_ACK");
    3009                 :            : 
    3010         [ -  + ]:         21 :         if (wps_parse_msg(msg, &attr) < 0)
    3011                 :          0 :                 return WPS_FAILURE;
    3012                 :            : 
    3013         [ -  + ]:         21 :         if (attr.msg_type == NULL) {
    3014                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
    3015                 :          0 :                 return WPS_FAILURE;
    3016                 :            :         }
    3017                 :            : 
    3018         [ -  + ]:         21 :         if (*attr.msg_type != WPS_WSC_ACK) {
    3019                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d",
    3020                 :          0 :                            *attr.msg_type);
    3021                 :          0 :                 return WPS_FAILURE;
    3022                 :            :         }
    3023                 :            : 
    3024                 :            : #ifdef CONFIG_WPS_UPNP
    3025 [ +  + ][ +  + ]:         30 :         if (wps->wps->wps_upnp && wps->ext_reg && wps->state == RECV_M2D_ACK &&
           [ +  -  +  - ]
    3026                 :          9 :             upnp_wps_subscribers(wps->wps->wps_upnp)) {
    3027         [ +  + ]:          9 :                 if (wps->wps->upnp_msgs)
    3028                 :          8 :                         return WPS_CONTINUE;
    3029                 :          1 :                 wpa_printf(MSG_DEBUG, "WPS: Wait for response from an "
    3030                 :            :                            "external Registrar");
    3031                 :          1 :                 return WPS_PENDING;
    3032                 :            :         }
    3033                 :            : #endif /* CONFIG_WPS_UPNP */
    3034                 :            : 
    3035 [ +  - ][ -  + ]:         12 :         if (attr.registrar_nonce == NULL ||
    3036                 :         12 :             os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN) != 0)
    3037                 :            :         {
    3038                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce");
    3039                 :          0 :                 return WPS_FAILURE;
    3040                 :            :         }
    3041                 :            : 
    3042 [ +  - ][ -  + ]:         12 :         if (attr.enrollee_nonce == NULL ||
    3043                 :         12 :             os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN) != 0) {
    3044                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce");
    3045                 :          0 :                 return WPS_FAILURE;
    3046                 :            :         }
    3047                 :            : 
    3048         [ +  - ]:         12 :         if (wps->state == RECV_M2D_ACK) {
    3049                 :            : #ifdef CONFIG_WPS_UPNP
    3050   [ +  +  +  - ]:         20 :                 if (wps->wps->wps_upnp &&
    3051                 :          8 :                     upnp_wps_subscribers(wps->wps->wps_upnp)) {
    3052         [ -  + ]:          8 :                         if (wps->wps->upnp_msgs)
    3053                 :          0 :                                 return WPS_CONTINUE;
    3054         [ +  - ]:          8 :                         if (wps->ext_reg == 0)
    3055                 :          8 :                                 wps->ext_reg = 1;
    3056                 :          8 :                         wpa_printf(MSG_DEBUG, "WPS: Wait for response from an "
    3057                 :            :                                    "external Registrar");
    3058                 :          8 :                         return WPS_PENDING;
    3059                 :            :                 }
    3060                 :            : #endif /* CONFIG_WPS_UPNP */
    3061                 :            : 
    3062                 :          4 :                 wpa_printf(MSG_DEBUG, "WPS: No more registrars available - "
    3063                 :            :                            "terminate negotiation");
    3064                 :            :         }
    3065                 :            : 
    3066                 :         21 :         return WPS_FAILURE;
    3067                 :            : }
    3068                 :            : 
    3069                 :            : 
    3070                 :         19 : static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps,
    3071                 :            :                                                  const struct wpabuf *msg)
    3072                 :            : {
    3073                 :            :         struct wps_parse_attr attr;
    3074                 :            :         int old_state;
    3075                 :            :         u16 config_error;
    3076                 :            : 
    3077                 :         19 :         wpa_printf(MSG_DEBUG, "WPS: Received WSC_NACK");
    3078                 :            : 
    3079                 :         19 :         old_state = wps->state;
    3080                 :         19 :         wps->state = SEND_WSC_NACK;
    3081                 :            : 
    3082         [ -  + ]:         19 :         if (wps_parse_msg(msg, &attr) < 0)
    3083                 :          0 :                 return WPS_FAILURE;
    3084                 :            : 
    3085         [ -  + ]:         19 :         if (attr.msg_type == NULL) {
    3086                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
    3087                 :          0 :                 return WPS_FAILURE;
    3088                 :            :         }
    3089                 :            : 
    3090         [ -  + ]:         19 :         if (*attr.msg_type != WPS_WSC_NACK) {
    3091                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d",
    3092                 :          0 :                            *attr.msg_type);
    3093                 :          0 :                 return WPS_FAILURE;
    3094                 :            :         }
    3095                 :            : 
    3096                 :            : #ifdef CONFIG_WPS_UPNP
    3097 [ +  + ][ +  - ]:         19 :         if (wps->wps->wps_upnp && wps->ext_reg) {
    3098                 :          1 :                 wpa_printf(MSG_DEBUG, "WPS: Negotiation using external "
    3099                 :            :                            "Registrar terminated by the Enrollee");
    3100                 :          1 :                 return WPS_FAILURE;
    3101                 :            :         }
    3102                 :            : #endif /* CONFIG_WPS_UPNP */
    3103                 :            : 
    3104 [ +  - ][ -  + ]:         18 :         if (attr.registrar_nonce == NULL ||
    3105                 :         18 :             os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN) != 0)
    3106                 :            :         {
    3107                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce");
    3108                 :          0 :                 return WPS_FAILURE;
    3109                 :            :         }
    3110                 :            : 
    3111 [ +  - ][ -  + ]:         18 :         if (attr.enrollee_nonce == NULL ||
    3112                 :         18 :             os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN) != 0) {
    3113                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce");
    3114                 :          0 :                 return WPS_FAILURE;
    3115                 :            :         }
    3116                 :            : 
    3117         [ -  + ]:         18 :         if (attr.config_error == NULL) {
    3118                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No Configuration Error attribute "
    3119                 :            :                            "in WSC_NACK");
    3120                 :          0 :                 return WPS_FAILURE;
    3121                 :            :         }
    3122                 :            : 
    3123                 :         18 :         config_error = WPA_GET_BE16(attr.config_error);
    3124                 :         18 :         wpa_printf(MSG_DEBUG, "WPS: Enrollee terminated negotiation with "
    3125                 :            :                    "Configuration Error %d", config_error);
    3126                 :            : 
    3127   [ +  +  +  +  :         18 :         switch (old_state) {
                      - ]
    3128                 :            :         case RECV_M3:
    3129                 :          6 :                 wps_fail_event(wps->wps, WPS_M2, config_error,
    3130                 :          6 :                                wps->error_indication, wps->mac_addr_e);
    3131                 :          6 :                 break;
    3132                 :            :         case RECV_M5:
    3133                 :          6 :                 wps_fail_event(wps->wps, WPS_M4, config_error,
    3134                 :          6 :                                wps->error_indication, wps->mac_addr_e);
    3135                 :          6 :                 break;
    3136                 :            :         case RECV_M7:
    3137                 :          3 :                 wps_fail_event(wps->wps, WPS_M6, config_error,
    3138                 :          3 :                                wps->error_indication, wps->mac_addr_e);
    3139                 :          3 :                 break;
    3140                 :            :         case RECV_DONE:
    3141                 :          3 :                 wps_fail_event(wps->wps, WPS_M8, config_error,
    3142                 :          3 :                                wps->error_indication, wps->mac_addr_e);
    3143                 :          3 :                 break;
    3144                 :            :         default:
    3145                 :          0 :                 break;
    3146                 :            :         }
    3147                 :            : 
    3148                 :         19 :         return WPS_FAILURE;
    3149                 :            : }
    3150                 :            : 
    3151                 :            : 
    3152                 :        117 : static enum wps_process_res wps_process_wsc_done(struct wps_data *wps,
    3153                 :            :                                                  const struct wpabuf *msg)
    3154                 :            : {
    3155                 :            :         struct wps_parse_attr attr;
    3156                 :            : 
    3157                 :        117 :         wpa_printf(MSG_DEBUG, "WPS: Received WSC_Done");
    3158                 :            : 
    3159 [ +  - ][ +  + ]:        117 :         if (wps->state != RECV_DONE &&
    3160         [ -  + ]:          6 :             (!wps->wps->wps_upnp || !wps->ext_reg)) {
    3161                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
    3162                 :          0 :                            "receiving WSC_Done", wps->state);
    3163                 :          0 :                 return WPS_FAILURE;
    3164                 :            :         }
    3165                 :            : 
    3166         [ -  + ]:        117 :         if (wps_parse_msg(msg, &attr) < 0)
    3167                 :          0 :                 return WPS_FAILURE;
    3168                 :            : 
    3169         [ -  + ]:        117 :         if (attr.msg_type == NULL) {
    3170                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
    3171                 :          0 :                 return WPS_FAILURE;
    3172                 :            :         }
    3173                 :            : 
    3174         [ -  + ]:        117 :         if (*attr.msg_type != WPS_WSC_DONE) {
    3175                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d",
    3176                 :          0 :                            *attr.msg_type);
    3177                 :          0 :                 return WPS_FAILURE;
    3178                 :            :         }
    3179                 :            : 
    3180                 :            : #ifdef CONFIG_WPS_UPNP
    3181 [ +  + ][ +  - ]:        117 :         if (wps->wps->wps_upnp && wps->ext_reg) {
    3182                 :          6 :                 wpa_printf(MSG_DEBUG, "WPS: Negotiation using external "
    3183                 :            :                            "Registrar completed successfully");
    3184                 :          6 :                 wps_device_store(wps->wps->registrar, &wps->peer_dev,
    3185                 :          6 :                                  wps->uuid_e);
    3186                 :          6 :                 return WPS_DONE;
    3187                 :            :         }
    3188                 :            : #endif /* CONFIG_WPS_UPNP */
    3189                 :            : 
    3190 [ +  - ][ -  + ]:        111 :         if (attr.registrar_nonce == NULL ||
    3191                 :        111 :             os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN) != 0)
    3192                 :            :         {
    3193                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce");
    3194                 :          0 :                 return WPS_FAILURE;
    3195                 :            :         }
    3196                 :            : 
    3197 [ +  - ][ -  + ]:        111 :         if (attr.enrollee_nonce == NULL ||
    3198                 :        111 :             os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN) != 0) {
    3199                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce");
    3200                 :          0 :                 return WPS_FAILURE;
    3201                 :            :         }
    3202                 :            : 
    3203                 :        111 :         wpa_printf(MSG_DEBUG, "WPS: Negotiation completed successfully");
    3204                 :        111 :         wps_device_store(wps->wps->registrar, &wps->peer_dev,
    3205                 :        111 :                          wps->uuid_e);
    3206                 :            : 
    3207 [ +  - ][ +  - ]:        111 :         if (wps->wps->wps_state == WPS_STATE_NOT_CONFIGURED && wps->new_psk &&
                 [ +  + ]
    3208         [ +  - ]:          5 :             wps->wps->ap && !wps->wps->registrar->disable_auto_conf) {
    3209                 :            :                 struct wps_credential cred;
    3210                 :            : 
    3211                 :          5 :                 wpa_printf(MSG_DEBUG, "WPS: Moving to Configured state based "
    3212                 :            :                            "on first Enrollee connection");
    3213                 :            : 
    3214                 :          5 :                 os_memset(&cred, 0, sizeof(cred));
    3215                 :          5 :                 os_memcpy(cred.ssid, wps->wps->ssid, wps->wps->ssid_len);
    3216                 :          5 :                 cred.ssid_len = wps->wps->ssid_len;
    3217                 :          5 :                 cred.auth_type = WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK;
    3218                 :          5 :                 cred.encr_type = WPS_ENCR_TKIP | WPS_ENCR_AES;
    3219                 :          5 :                 os_memcpy(cred.key, wps->new_psk, wps->new_psk_len);
    3220                 :          5 :                 cred.key_len = wps->new_psk_len;
    3221                 :            : 
    3222                 :          5 :                 wps->wps->wps_state = WPS_STATE_CONFIGURED;
    3223                 :          5 :                 wpa_hexdump_ascii_key(MSG_DEBUG,
    3224                 :            :                                       "WPS: Generated random passphrase",
    3225                 :          5 :                                       wps->new_psk, wps->new_psk_len);
    3226         [ +  - ]:          5 :                 if (wps->wps->cred_cb)
    3227                 :          5 :                         wps->wps->cred_cb(wps->wps->cb_ctx, &cred);
    3228                 :            : 
    3229                 :          5 :                 os_free(wps->new_psk);
    3230                 :          5 :                 wps->new_psk = NULL;
    3231                 :            :         }
    3232                 :            : 
    3233 [ +  + ][ +  + ]:        111 :         if (!wps->wps->ap && !wps->er)
    3234                 :          5 :                 wps_sta_cred_cb(wps);
    3235                 :            : 
    3236         [ +  + ]:        111 :         if (wps->new_psk) {
    3237         [ -  + ]:          8 :                 if (wps_cb_new_psk(wps->wps->registrar, wps->mac_addr_e,
    3238                 :          8 :                                    wps->p2p_dev_addr, wps->new_psk,
    3239                 :            :                                    wps->new_psk_len)) {
    3240                 :          0 :                         wpa_printf(MSG_DEBUG, "WPS: Failed to configure the "
    3241                 :            :                                    "new PSK");
    3242                 :            :                 }
    3243                 :          8 :                 os_free(wps->new_psk);
    3244                 :          8 :                 wps->new_psk = NULL;
    3245                 :            :         }
    3246                 :            : 
    3247                 :        111 :         wps_cb_reg_success(wps->wps->registrar, wps->mac_addr_e, wps->uuid_e,
    3248                 :        111 :                            wps->dev_password, wps->dev_password_len);
    3249                 :            : 
    3250         [ +  + ]:        111 :         if (wps->pbc) {
    3251                 :         15 :                 wps_registrar_remove_pbc_session(wps->wps->registrar,
    3252                 :         15 :                                                  wps->uuid_e,
    3253                 :         15 :                                                  wps->p2p_dev_addr);
    3254                 :         15 :                 wps_registrar_pbc_completed(wps->wps->registrar);
    3255                 :            : #ifdef WPS_WORKAROUNDS
    3256                 :         15 :                 os_get_reltime(&wps->wps->registrar->pbc_ignore_start);
    3257                 :            : #endif /* WPS_WORKAROUNDS */
    3258                 :         15 :                 os_memcpy(wps->wps->registrar->pbc_ignore_uuid, wps->uuid_e,
    3259                 :            :                           WPS_UUID_LEN);
    3260                 :            :         } else {
    3261                 :         96 :                 wps_registrar_pin_completed(wps->wps->registrar);
    3262                 :            :         }
    3263                 :            :         /* TODO: maintain AuthorizedMACs somewhere separately for each ER and
    3264                 :            :          * merge them into APs own list.. */
    3265                 :            : 
    3266                 :        111 :         wps_success_event(wps->wps, wps->mac_addr_e);
    3267                 :            : 
    3268                 :        117 :         return WPS_DONE;
    3269                 :            : }
    3270                 :            : 
    3271                 :            : 
    3272                 :        692 : enum wps_process_res wps_registrar_process_msg(struct wps_data *wps,
    3273                 :            :                                                enum wsc_op_code op_code,
    3274                 :            :                                                const struct wpabuf *msg)
    3275                 :            : {
    3276                 :            :         enum wps_process_res ret;
    3277                 :            : 
    3278                 :        692 :         wpa_printf(MSG_DEBUG, "WPS: Processing received message (len=%lu "
    3279                 :            :                    "op_code=%d)",
    3280                 :            :                    (unsigned long) wpabuf_len(msg), op_code);
    3281                 :            : 
    3282                 :            : #ifdef CONFIG_WPS_UPNP
    3283 [ +  + ][ +  + ]:        692 :         if (wps->wps->wps_upnp && op_code == WSC_MSG && wps->ext_reg == 1) {
                 [ +  + ]
    3284                 :            :                 struct wps_parse_attr attr;
    3285 [ +  - ][ +  - ]:          5 :                 if (wps_parse_msg(msg, &attr) == 0 && attr.msg_type &&
                 [ +  - ]
    3286                 :          5 :                     *attr.msg_type == WPS_M3)
    3287                 :          5 :                         wps->ext_reg = 2; /* past M2/M2D phase */
    3288                 :            :         }
    3289         [ +  + ]:        692 :         if (wps->ext_reg > 1)
    3290                 :         35 :                 wps_registrar_free_pending_m2(wps->wps);
    3291 [ +  + ][ +  + ]:        692 :         if (wps->wps->wps_upnp && wps->ext_reg &&
                 [ +  + ]
    3292         [ +  + ]:         23 :             wps->wps->upnp_msgs == NULL &&
    3293 [ +  + ][ +  + ]:          8 :             (op_code == WSC_MSG || op_code == WSC_Done || op_code == WSC_NACK))
    3294                 :          7 :         {
    3295                 :            :                 struct wps_parse_attr attr;
    3296                 :            :                 int type;
    3297 [ +  - ][ -  + ]:         22 :                 if (wps_parse_msg(msg, &attr) < 0 || attr.msg_type == NULL)
    3298                 :          0 :                         type = -1;
    3299                 :            :                 else
    3300                 :         22 :                         type = *attr.msg_type;
    3301                 :         22 :                 wpa_printf(MSG_DEBUG, "WPS: Sending received message (type %d)"
    3302                 :            :                            " to external Registrar for processing", type);
    3303                 :         22 :                 upnp_wps_device_send_wlan_event(wps->wps->wps_upnp,
    3304                 :         22 :                                                 wps->mac_addr_e,
    3305                 :            :                                                 UPNP_WPS_WLANEVENT_TYPE_EAP,
    3306                 :            :                                                 msg);
    3307         [ +  + ]:         22 :                 if (op_code == WSC_MSG)
    3308                 :         15 :                         return WPS_PENDING;
    3309 [ +  + ][ +  + ]:        670 :         } else if (wps->wps->wps_upnp && wps->ext_reg && op_code == WSC_MSG) {
                 [ +  + ]
    3310                 :         15 :                 wpa_printf(MSG_DEBUG, "WPS: Skip internal processing - using "
    3311                 :            :                            "external Registrar");
    3312                 :         15 :                 return WPS_CONTINUE;
    3313                 :            :         }
    3314                 :            : #endif /* CONFIG_WPS_UPNP */
    3315                 :            : 
    3316   [ +  +  +  +  :        662 :         switch (op_code) {
                      - ]
    3317                 :            :         case WSC_MSG:
    3318                 :        505 :                 return wps_process_wsc_msg(wps, msg);
    3319                 :            :         case WSC_ACK:
    3320         [ -  + ]:         21 :                 if (wps_validate_wsc_ack(msg) < 0)
    3321                 :          0 :                         return WPS_FAILURE;
    3322                 :         21 :                 return wps_process_wsc_ack(wps, msg);
    3323                 :            :         case WSC_NACK:
    3324         [ -  + ]:         19 :                 if (wps_validate_wsc_nack(msg) < 0)
    3325                 :          0 :                         return WPS_FAILURE;
    3326                 :         19 :                 return wps_process_wsc_nack(wps, msg);
    3327                 :            :         case WSC_Done:
    3328         [ -  + ]:        117 :                 if (wps_validate_wsc_done(msg) < 0)
    3329                 :          0 :                         return WPS_FAILURE;
    3330                 :        117 :                 ret = wps_process_wsc_done(wps, msg);
    3331         [ -  + ]:        117 :                 if (ret == WPS_FAILURE) {
    3332                 :          0 :                         wps->state = SEND_WSC_NACK;
    3333                 :          0 :                         wps_fail_event(wps->wps, WPS_WSC_DONE,
    3334                 :          0 :                                        wps->config_error,
    3335                 :          0 :                                        wps->error_indication, wps->mac_addr_e);
    3336                 :            :                 }
    3337                 :        117 :                 return ret;
    3338                 :            :         default:
    3339                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Unsupported op_code %d", op_code);
    3340                 :        692 :                 return WPS_FAILURE;
    3341                 :            :         }
    3342                 :            : }
    3343                 :            : 
    3344                 :            : 
    3345                 :         18 : int wps_registrar_update_ie(struct wps_registrar *reg)
    3346                 :            : {
    3347                 :         18 :         return wps_set_ie(reg);
    3348                 :            : }
    3349                 :            : 
    3350                 :            : 
    3351                 :          3 : static void wps_registrar_set_selected_timeout(void *eloop_ctx,
    3352                 :            :                                                void *timeout_ctx)
    3353                 :            : {
    3354                 :          3 :         struct wps_registrar *reg = eloop_ctx;
    3355                 :            : 
    3356                 :          3 :         wpa_printf(MSG_DEBUG, "WPS: Selected Registrar timeout - "
    3357                 :            :                    "unselect internal Registrar");
    3358                 :          3 :         reg->selected_registrar = 0;
    3359                 :          3 :         reg->pbc = 0;
    3360                 :          3 :         wps_registrar_selected_registrar_changed(reg, 0);
    3361                 :          3 : }
    3362                 :            : 
    3363                 :            : 
    3364                 :            : #ifdef CONFIG_WPS_UPNP
    3365                 :         12 : static void wps_registrar_sel_reg_add(struct wps_registrar *reg,
    3366                 :            :                                       struct subscription *s)
    3367                 :            : {
    3368                 :            :         int i, j;
    3369                 :         12 :         wpa_printf(MSG_DEBUG, "WPS: External Registrar selected (dev_pw_id=%d "
    3370                 :            :                    "config_methods=0x%x)",
    3371                 :         24 :                    s->dev_password_id, s->config_methods);
    3372                 :         12 :         reg->sel_reg_union = 1;
    3373         [ +  - ]:         12 :         if (reg->sel_reg_dev_password_id_override != DEV_PW_PUSHBUTTON)
    3374                 :         12 :                 reg->sel_reg_dev_password_id_override = s->dev_password_id;
    3375         [ +  - ]:         12 :         if (reg->sel_reg_config_methods_override == -1)
    3376                 :         12 :                 reg->sel_reg_config_methods_override = 0;
    3377                 :         12 :         reg->sel_reg_config_methods_override |= s->config_methods;
    3378         [ +  - ]:         12 :         for (i = 0; i < WPS_MAX_AUTHORIZED_MACS; i++)
    3379         [ +  - ]:         12 :                 if (is_zero_ether_addr(reg->authorized_macs_union[i]))
    3380                 :         12 :                         break;
    3381 [ +  - ][ +  - ]:         24 :         for (j = 0; i < WPS_MAX_AUTHORIZED_MACS && j < WPS_MAX_AUTHORIZED_MACS;
    3382                 :         12 :              j++) {
    3383         [ +  + ]:         24 :                 if (is_zero_ether_addr(s->authorized_macs[j]))
    3384                 :         12 :                         break;
    3385                 :         12 :                 wpa_printf(MSG_DEBUG, "WPS: Add authorized MAC into union: "
    3386                 :         72 :                            MACSTR, MAC2STR(s->authorized_macs[j]));
    3387                 :         12 :                 os_memcpy(reg->authorized_macs_union[i],
    3388                 :            :                           s->authorized_macs[j], ETH_ALEN);
    3389                 :         12 :                 i++;
    3390                 :            :         }
    3391                 :         12 :         wpa_hexdump(MSG_DEBUG, "WPS: Authorized MACs union",
    3392                 :         12 :                     (u8 *) reg->authorized_macs_union,
    3393                 :            :                     sizeof(reg->authorized_macs_union));
    3394                 :         12 : }
    3395                 :            : #endif /* CONFIG_WPS_UPNP */
    3396                 :            : 
    3397                 :            : 
    3398                 :        428 : static void wps_registrar_sel_reg_union(struct wps_registrar *reg)
    3399                 :            : {
    3400                 :            : #ifdef CONFIG_WPS_UPNP
    3401                 :            :         struct subscription *s;
    3402                 :            : 
    3403         [ +  + ]:        428 :         if (reg->wps->wps_upnp == NULL)
    3404                 :        428 :                 return;
    3405                 :            : 
    3406         [ +  + ]:         47 :         dl_list_for_each(s, &reg->wps->wps_upnp->subscriptions,
    3407                 :            :                          struct subscription, list) {
    3408                 :            :                 struct subscr_addr *sa;
    3409         [ +  - ]:         18 :                 sa = dl_list_first(&s->addr_list, struct subscr_addr, list);
    3410         [ +  - ]:         18 :                 if (sa) {
    3411                 :         18 :                         wpa_printf(MSG_DEBUG, "WPS: External Registrar %s:%d",
    3412                 :            :                                    inet_ntoa(sa->saddr.sin_addr),
    3413                 :         18 :                                    ntohs(sa->saddr.sin_port));
    3414                 :            :                 }
    3415         [ +  + ]:         18 :                 if (s->selected_registrar)
    3416                 :         12 :                         wps_registrar_sel_reg_add(reg, s);
    3417                 :            :                 else
    3418                 :          6 :                         wpa_printf(MSG_DEBUG, "WPS: External Registrar not "
    3419                 :            :                                    "selected");
    3420                 :            :         }
    3421                 :            : #endif /* CONFIG_WPS_UPNP */
    3422                 :            : }
    3423                 :            : 
    3424                 :            : 
    3425                 :            : /**
    3426                 :            :  * wps_registrar_selected_registrar_changed - SetSelectedRegistrar change
    3427                 :            :  * @reg: Registrar data from wps_registrar_init()
    3428                 :            :  *
    3429                 :            :  * This function is called when selected registrar state changes, e.g., when an
    3430                 :            :  * AP receives a SetSelectedRegistrar UPnP message.
    3431                 :            :  */
    3432                 :        428 : void wps_registrar_selected_registrar_changed(struct wps_registrar *reg,
    3433                 :            :                                               u16 dev_pw_id)
    3434                 :            : {
    3435                 :        428 :         wpa_printf(MSG_DEBUG, "WPS: Selected registrar information changed");
    3436                 :            : 
    3437                 :        428 :         reg->sel_reg_union = reg->selected_registrar;
    3438                 :        428 :         reg->sel_reg_dev_password_id_override = -1;
    3439                 :        428 :         reg->sel_reg_config_methods_override = -1;
    3440                 :        428 :         os_memcpy(reg->authorized_macs_union, reg->authorized_macs,
    3441                 :            :                   WPS_MAX_AUTHORIZED_MACS * ETH_ALEN);
    3442                 :        428 :         wpa_hexdump(MSG_DEBUG, "WPS: Authorized MACs union (start with own)",
    3443                 :        428 :                     (u8 *) reg->authorized_macs_union,
    3444                 :            :                     sizeof(reg->authorized_macs_union));
    3445         [ +  + ]:        428 :         if (reg->selected_registrar) {
    3446                 :            :                 u16 methods;
    3447                 :            : 
    3448                 :        246 :                 methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON;
    3449                 :            : #ifdef CONFIG_WPS2
    3450                 :        246 :                 methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON |
    3451                 :            :                              WPS_CONFIG_PHY_PUSHBUTTON);
    3452                 :            : #endif /* CONFIG_WPS2 */
    3453         [ +  + ]:        246 :                 if (reg->pbc) {
    3454                 :         21 :                         reg->sel_reg_dev_password_id_override =
    3455                 :            :                                 DEV_PW_PUSHBUTTON;
    3456                 :         21 :                         wps_set_pushbutton(&methods, reg->wps->config_methods);
    3457         [ +  + ]:        225 :                 } else if (dev_pw_id)
    3458                 :         23 :                         reg->sel_reg_dev_password_id_override = dev_pw_id;
    3459                 :        246 :                 wpa_printf(MSG_DEBUG, "WPS: Internal Registrar selected "
    3460                 :            :                            "(pbc=%d)", reg->pbc);
    3461                 :        246 :                 reg->sel_reg_config_methods_override = methods;
    3462                 :            :         } else
    3463                 :        182 :                 wpa_printf(MSG_DEBUG, "WPS: Internal Registrar not selected");
    3464                 :            : 
    3465                 :        428 :         wps_registrar_sel_reg_union(reg);
    3466                 :            : 
    3467                 :        428 :         wps_set_ie(reg);
    3468                 :        428 :         wps_cb_set_sel_reg(reg);
    3469                 :        428 : }
    3470                 :            : 
    3471                 :            : 
    3472                 :          4 : int wps_registrar_get_info(struct wps_registrar *reg, const u8 *addr,
    3473                 :            :                            char *buf, size_t buflen)
    3474                 :            : {
    3475                 :            :         struct wps_registrar_device *d;
    3476                 :          4 :         int len = 0, ret;
    3477                 :            :         char uuid[40];
    3478                 :            :         char devtype[WPS_DEV_TYPE_BUFSIZE];
    3479                 :            : 
    3480                 :          4 :         d = wps_device_get(reg, addr);
    3481         [ +  + ]:          4 :         if (d == NULL)
    3482                 :          3 :                 return 0;
    3483         [ -  + ]:          1 :         if (uuid_bin2str(d->uuid, uuid, sizeof(uuid)))
    3484                 :          0 :                 return 0;
    3485                 :            : 
    3486 [ +  - ][ +  - ]:          1 :         ret = os_snprintf(buf + len, buflen - len,
         [ +  - ][ +  - ]
                 [ +  - ]
    3487                 :            :                           "wpsUuid=%s\n"
    3488                 :            :                           "wpsPrimaryDeviceType=%s\n"
    3489                 :            :                           "wpsDeviceName=%s\n"
    3490                 :            :                           "wpsManufacturer=%s\n"
    3491                 :            :                           "wpsModelName=%s\n"
    3492                 :            :                           "wpsModelNumber=%s\n"
    3493                 :            :                           "wpsSerialNumber=%s\n",
    3494                 :            :                           uuid,
    3495                 :          1 :                           wps_dev_type_bin2str(d->dev.pri_dev_type, devtype,
    3496                 :            :                                                sizeof(devtype)),
    3497                 :          1 :                           d->dev.device_name ? d->dev.device_name : "",
    3498                 :          1 :                           d->dev.manufacturer ? d->dev.manufacturer : "",
    3499                 :          1 :                           d->dev.model_name ? d->dev.model_name : "",
    3500                 :          1 :                           d->dev.model_number ? d->dev.model_number : "",
    3501                 :          1 :                           d->dev.serial_number ? d->dev.serial_number : "");
    3502 [ -  + ][ +  - ]:          1 :         if (ret < 0 || (size_t) ret >= buflen - len)
    3503                 :          0 :                 return len;
    3504                 :          1 :         len += ret;
    3505                 :            : 
    3506                 :          4 :         return len;
    3507                 :            : }
    3508                 :            : 
    3509                 :            : 
    3510                 :          1 : int wps_registrar_config_ap(struct wps_registrar *reg,
    3511                 :            :                             struct wps_credential *cred)
    3512                 :            : {
    3513                 :            : #ifdef CONFIG_WPS2
    3514                 :          1 :         wpa_printf(MSG_DEBUG, "WPS: encr_type=0x%x", cred->encr_type);
    3515         [ -  + ]:          1 :         if (!(cred->encr_type & (WPS_ENCR_NONE | WPS_ENCR_TKIP |
    3516                 :            :                                  WPS_ENCR_AES))) {
    3517         [ #  # ]:          0 :                 if (cred->encr_type & WPS_ENCR_WEP) {
    3518                 :          0 :                         wpa_printf(MSG_INFO, "WPS: Reject new AP settings "
    3519                 :            :                                    "due to WEP configuration");
    3520                 :          0 :                         return -1;
    3521                 :            :                 }
    3522                 :            : 
    3523                 :          0 :                 wpa_printf(MSG_INFO, "WPS: Reject new AP settings due to "
    3524                 :          0 :                            "invalid encr_type 0x%x", cred->encr_type);
    3525                 :          0 :                 return -1;
    3526                 :            :         }
    3527                 :            : 
    3528         [ -  + ]:          1 :         if ((cred->encr_type & (WPS_ENCR_TKIP | WPS_ENCR_AES)) ==
    3529                 :            :             WPS_ENCR_TKIP) {
    3530                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Upgrade encr_type TKIP -> "
    3531                 :            :                            "TKIP+AES");
    3532                 :          0 :                 cred->encr_type |= WPS_ENCR_AES;
    3533                 :            :         }
    3534                 :            : 
    3535         [ -  + ]:          1 :         if ((cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) ==
    3536                 :            :             WPS_AUTH_WPAPSK) {
    3537                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Upgrade auth_type WPAPSK -> "
    3538                 :            :                            "WPAPSK+WPA2PSK");
    3539                 :          0 :                 cred->auth_type |= WPS_AUTH_WPA2PSK;
    3540                 :            :         }
    3541                 :            : #endif /* CONFIG_WPS2 */
    3542                 :            : 
    3543         [ +  - ]:          1 :         if (reg->wps->cred_cb)
    3544                 :          1 :                 return reg->wps->cred_cb(reg->wps->cb_ctx, cred);
    3545                 :            : 
    3546                 :          1 :         return -1;
    3547                 :            : }
    3548                 :            : 
    3549                 :            : 
    3550                 :            : #ifdef CONFIG_WPS_NFC
    3551                 :            : 
    3552                 :         23 : int wps_registrar_add_nfc_pw_token(struct wps_registrar *reg,
    3553                 :            :                                    const u8 *pubkey_hash, u16 pw_id,
    3554                 :            :                                    const u8 *dev_pw, size_t dev_pw_len,
    3555                 :            :                                    int pk_hash_provided_oob)
    3556                 :            : {
    3557                 :            :         struct wps_nfc_pw_token *token;
    3558                 :            : 
    3559         [ -  + ]:         23 :         if (dev_pw_len > WPS_OOB_DEVICE_PASSWORD_LEN)
    3560                 :          0 :                 return -1;
    3561                 :            : 
    3562 [ +  + ][ +  - ]:         23 :         if (pw_id == DEV_PW_NFC_CONNECTION_HANDOVER &&
    3563         [ -  + ]:         15 :             (pubkey_hash == NULL || !pk_hash_provided_oob)) {
    3564                 :          0 :                 wpa_printf(MSG_DEBUG, "WPS: Unexpected NFC Password Token "
    3565                 :            :                            "addition - missing public key hash");
    3566                 :          0 :                 return -1;
    3567                 :            :         }
    3568                 :            : 
    3569                 :         23 :         wps_free_nfc_pw_tokens(&reg->nfc_pw_tokens, pw_id);
    3570                 :            : 
    3571                 :         23 :         token = os_zalloc(sizeof(*token));
    3572         [ -  + ]:         23 :         if (token == NULL)
    3573                 :          0 :                 return -1;
    3574                 :            : 
    3575                 :         23 :         token->peer_pk_hash_known = pubkey_hash != NULL;
    3576         [ +  + ]:         23 :         if (pubkey_hash)
    3577                 :         22 :                 os_memcpy(token->pubkey_hash, pubkey_hash,
    3578                 :            :                           WPS_OOB_PUBKEY_HASH_LEN);
    3579                 :         23 :         token->pw_id = pw_id;
    3580                 :         23 :         token->pk_hash_provided_oob = pk_hash_provided_oob;
    3581         [ +  + ]:         23 :         if (dev_pw) {
    3582                 :          8 :                 wpa_snprintf_hex_uppercase((char *) token->dev_pw,
    3583                 :            :                                            sizeof(token->dev_pw),
    3584                 :            :                                            dev_pw, dev_pw_len);
    3585                 :          8 :                 token->dev_pw_len = dev_pw_len * 2;
    3586                 :            :         }
    3587                 :            : 
    3588                 :         23 :         dl_list_add(&reg->nfc_pw_tokens, &token->list);
    3589                 :            : 
    3590                 :         23 :         reg->selected_registrar = 1;
    3591                 :         23 :         reg->pbc = 0;
    3592                 :         23 :         wps_registrar_add_authorized_mac(reg,
    3593                 :            :                                          (u8 *) "\xff\xff\xff\xff\xff\xff");
    3594                 :         23 :         wps_registrar_selected_registrar_changed(reg, pw_id);
    3595                 :         23 :         eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
    3596                 :         23 :         eloop_register_timeout(WPS_PBC_WALK_TIME, 0,
    3597                 :            :                                wps_registrar_set_selected_timeout,
    3598                 :            :                                reg, NULL);
    3599                 :            : 
    3600                 :         23 :         wpa_printf(MSG_DEBUG, "WPS: Added NFC Device Password %u to Registrar",
    3601                 :            :                    pw_id);
    3602                 :            : 
    3603                 :         23 :         return 0;
    3604                 :            : }
    3605                 :            : 
    3606                 :            : 
    3607                 :          4 : int wps_registrar_add_nfc_password_token(struct wps_registrar *reg,
    3608                 :            :                                          const u8 *oob_dev_pw,
    3609                 :            :                                          size_t oob_dev_pw_len)
    3610                 :            : {
    3611                 :            :         const u8 *pos, *hash, *dev_pw;
    3612                 :            :         u16 id;
    3613                 :            :         size_t dev_pw_len;
    3614                 :            : 
    3615 [ +  - ][ -  + ]:          4 :         if (oob_dev_pw_len < WPS_OOB_PUBKEY_HASH_LEN + 2 ||
    3616                 :            :             oob_dev_pw_len > WPS_OOB_PUBKEY_HASH_LEN + 2 +
    3617                 :            :             WPS_OOB_DEVICE_PASSWORD_LEN)
    3618                 :          0 :                 return -1;
    3619                 :            : 
    3620                 :          4 :         hash = oob_dev_pw;
    3621                 :          4 :         pos = oob_dev_pw + WPS_OOB_PUBKEY_HASH_LEN;
    3622                 :          4 :         id = WPA_GET_BE16(pos);
    3623                 :          4 :         dev_pw = pos + 2;
    3624                 :          4 :         dev_pw_len = oob_dev_pw + oob_dev_pw_len - dev_pw;
    3625                 :            : 
    3626                 :          4 :         wpa_printf(MSG_DEBUG, "WPS: Add NFC Password Token for Password ID %u",
    3627                 :            :                    id);
    3628                 :            : 
    3629                 :          4 :         wpa_hexdump(MSG_DEBUG, "WPS: Public Key Hash",
    3630                 :            :                     hash, WPS_OOB_PUBKEY_HASH_LEN);
    3631                 :          4 :         wpa_hexdump_key(MSG_DEBUG, "WPS: Device Password", dev_pw, dev_pw_len);
    3632                 :            : 
    3633                 :          4 :         return wps_registrar_add_nfc_pw_token(reg, hash, id, dev_pw,
    3634                 :            :                                               dev_pw_len, 0);
    3635                 :            : }
    3636                 :            : 
    3637                 :            : 
    3638                 :         23 : void wps_registrar_remove_nfc_pw_token(struct wps_registrar *reg,
    3639                 :            :                                        struct wps_nfc_pw_token *token)
    3640                 :            : {
    3641                 :         23 :         wps_registrar_remove_authorized_mac(reg,
    3642                 :            :                                             (u8 *) "\xff\xff\xff\xff\xff\xff");
    3643                 :         23 :         wps_registrar_selected_registrar_changed(reg, 0);
    3644                 :            : 
    3645                 :            :         /*
    3646                 :            :          * Free the NFC password token if it was used only for a single protocol
    3647                 :            :          * run. The static handover case uses the same password token multiple
    3648                 :            :          * times, so do not free that case here.
    3649                 :            :          */
    3650         [ +  + ]:         23 :         if (token->peer_pk_hash_known)
    3651                 :         22 :                 os_free(token);
    3652                 :         23 : }
    3653                 :            : 
    3654                 :            : #endif /* CONFIG_WPS_NFC */

Generated by: LCOV version 1.9