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 1401264779 Lines: 1579 1939 81.4 %
Date: 2014-05-28 Functions: 112 113 99.1 %

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

Generated by: LCOV version 1.10