LCOV - code coverage report
Current view: top level - wps - wps_registrar.c (source / functions) Hit Total Coverage
Test: hostapd hwsim test run 1412854115 Lines: 1427 1925 74.1 %
Date: 2014-10-09 Functions: 106 113 93.8 %

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

Generated by: LCOV version 1.10