LCOV - code coverage report
Current view: top level - src/wps - wps_registrar.c (source / functions) Hit Total Coverage
Test: wpa_supplicant hwsim test run 1388240082 Lines: 1164 1877 62.0 %
Date: 2013-12-28 Functions: 96 113 85.0 %
Branches: 501 1132 44.3 %

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

Generated by: LCOV version 1.9