LCOV - code coverage report
Current view: top level - src/wps - wps_registrar.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1443382998 Lines: 1774 1958 90.6 %
Date: 2015-09-27 Functions: 114 114 100.0 %

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

Generated by: LCOV version 1.10