LCOV - code coverage report
Current view: top level - wps - wps_enrollee.c (source / functions) Hit Total Coverage
Test: hostapd hwsim test run 1412854115 Lines: 501 812 61.7 %
Date: 2014-10-09 Functions: 35 37 94.6 %

          Line data    Source code
       1             : /*
       2             :  * Wi-Fi Protected Setup - Enrollee
       3             :  * Copyright (c) 2008, 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 "includes.h"
      10             : 
      11             : #include "common.h"
      12             : #include "crypto/crypto.h"
      13             : #include "crypto/sha256.h"
      14             : #include "crypto/random.h"
      15             : #include "wps_i.h"
      16             : #include "wps_dev_attr.h"
      17             : 
      18             : 
      19          45 : static int wps_build_wps_state(struct wps_data *wps, struct wpabuf *msg)
      20             : {
      21             :         u8 state;
      22          45 :         if (wps->wps->ap)
      23          45 :                 state = wps->wps->wps_state;
      24             :         else
      25           0 :                 state = WPS_STATE_NOT_CONFIGURED;
      26          45 :         wpa_printf(MSG_DEBUG, "WPS:  * Wi-Fi Protected Setup State (%d)",
      27             :                    state);
      28          45 :         wpabuf_put_be16(msg, ATTR_WPS_STATE);
      29          45 :         wpabuf_put_be16(msg, 1);
      30          45 :         wpabuf_put_u8(msg, state);
      31          45 :         return 0;
      32             : }
      33             : 
      34             : 
      35          29 : static int wps_build_e_hash(struct wps_data *wps, struct wpabuf *msg)
      36             : {
      37             :         u8 *hash;
      38             :         const u8 *addr[4];
      39             :         size_t len[4];
      40             : 
      41          29 :         if (random_get_bytes(wps->snonce, 2 * WPS_SECRET_NONCE_LEN) < 0)
      42           0 :                 return -1;
      43          29 :         wpa_hexdump(MSG_DEBUG, "WPS: E-S1", wps->snonce, WPS_SECRET_NONCE_LEN);
      44          29 :         wpa_hexdump(MSG_DEBUG, "WPS: E-S2",
      45          29 :                     wps->snonce + WPS_SECRET_NONCE_LEN, WPS_SECRET_NONCE_LEN);
      46             : 
      47          29 :         if (wps->dh_pubkey_e == NULL || wps->dh_pubkey_r == NULL) {
      48           0 :                 wpa_printf(MSG_DEBUG, "WPS: DH public keys not available for "
      49             :                            "E-Hash derivation");
      50           0 :                 return -1;
      51             :         }
      52             : 
      53          29 :         wpa_printf(MSG_DEBUG, "WPS:  * E-Hash1");
      54          29 :         wpabuf_put_be16(msg, ATTR_E_HASH1);
      55          29 :         wpabuf_put_be16(msg, SHA256_MAC_LEN);
      56          29 :         hash = wpabuf_put(msg, SHA256_MAC_LEN);
      57             :         /* E-Hash1 = HMAC_AuthKey(E-S1 || PSK1 || PK_E || PK_R) */
      58          29 :         addr[0] = wps->snonce;
      59          29 :         len[0] = WPS_SECRET_NONCE_LEN;
      60          29 :         addr[1] = wps->psk1;
      61          29 :         len[1] = WPS_PSK_LEN;
      62          29 :         addr[2] = wpabuf_head(wps->dh_pubkey_e);
      63          29 :         len[2] = wpabuf_len(wps->dh_pubkey_e);
      64          29 :         addr[3] = wpabuf_head(wps->dh_pubkey_r);
      65          29 :         len[3] = wpabuf_len(wps->dh_pubkey_r);
      66          29 :         hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
      67          29 :         wpa_hexdump(MSG_DEBUG, "WPS: E-Hash1", hash, SHA256_MAC_LEN);
      68             : 
      69          29 :         wpa_printf(MSG_DEBUG, "WPS:  * E-Hash2");
      70          29 :         wpabuf_put_be16(msg, ATTR_E_HASH2);
      71          29 :         wpabuf_put_be16(msg, SHA256_MAC_LEN);
      72          29 :         hash = wpabuf_put(msg, SHA256_MAC_LEN);
      73             :         /* E-Hash2 = HMAC_AuthKey(E-S2 || PSK2 || PK_E || PK_R) */
      74          29 :         addr[0] = wps->snonce + WPS_SECRET_NONCE_LEN;
      75          29 :         addr[1] = wps->psk2;
      76          29 :         hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
      77          29 :         wpa_hexdump(MSG_DEBUG, "WPS: E-Hash2", hash, SHA256_MAC_LEN);
      78             : 
      79          29 :         return 0;
      80             : }
      81             : 
      82             : 
      83          25 : static int wps_build_e_snonce1(struct wps_data *wps, struct wpabuf *msg)
      84             : {
      85          25 :         wpa_printf(MSG_DEBUG, "WPS:  * E-SNonce1");
      86          25 :         wpabuf_put_be16(msg, ATTR_E_SNONCE1);
      87          25 :         wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN);
      88          25 :         wpabuf_put_data(msg, wps->snonce, WPS_SECRET_NONCE_LEN);
      89          25 :         return 0;
      90             : }
      91             : 
      92             : 
      93          23 : static int wps_build_e_snonce2(struct wps_data *wps, struct wpabuf *msg)
      94             : {
      95          23 :         wpa_printf(MSG_DEBUG, "WPS:  * E-SNonce2");
      96          23 :         wpabuf_put_be16(msg, ATTR_E_SNONCE2);
      97          23 :         wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN);
      98          23 :         wpabuf_put_data(msg, wps->snonce + WPS_SECRET_NONCE_LEN,
      99             :                         WPS_SECRET_NONCE_LEN);
     100          23 :         return 0;
     101             : }
     102             : 
     103             : 
     104          45 : static struct wpabuf * wps_build_m1(struct wps_data *wps)
     105             : {
     106             :         struct wpabuf *msg;
     107             :         u16 config_methods;
     108             : 
     109          45 :         if (random_get_bytes(wps->nonce_e, WPS_NONCE_LEN) < 0)
     110           0 :                 return NULL;
     111          45 :         wpa_hexdump(MSG_DEBUG, "WPS: Enrollee Nonce",
     112          45 :                     wps->nonce_e, WPS_NONCE_LEN);
     113             : 
     114          45 :         wpa_printf(MSG_DEBUG, "WPS: Building Message M1");
     115          45 :         msg = wpabuf_alloc(1000);
     116          45 :         if (msg == NULL)
     117           0 :                 return NULL;
     118             : 
     119          45 :         config_methods = wps->wps->config_methods;
     120          90 :         if (wps->wps->ap && !wps->pbc_in_m1 &&
     121          48 :             (wps->dev_password_len != 0 ||
     122           3 :              (config_methods & WPS_CONFIG_DISPLAY))) {
     123             :                 /*
     124             :                  * These are the methods that the AP supports as an Enrollee
     125             :                  * for adding external Registrars, so remove PushButton.
     126             :                  *
     127             :                  * As a workaround for Windows 7 mechanism for probing WPS
     128             :                  * capabilities from M1, leave PushButton option if no PIN
     129             :                  * method is available or if WPS configuration enables PBC
     130             :                  * workaround.
     131             :                  */
     132          42 :                 config_methods &= ~WPS_CONFIG_PUSHBUTTON;
     133          42 :                 config_methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON |
     134             :                                     WPS_CONFIG_PHY_PUSHBUTTON);
     135             :         }
     136             : 
     137          90 :         if (wps_build_version(msg) ||
     138          90 :             wps_build_msg_type(msg, WPS_M1) ||
     139          90 :             wps_build_uuid_e(msg, wps->uuid_e) ||
     140          90 :             wps_build_mac_addr(msg, wps->mac_addr_e) ||
     141          90 :             wps_build_enrollee_nonce(wps, msg) ||
     142          90 :             wps_build_public_key(wps, msg) ||
     143          90 :             wps_build_auth_type_flags(wps, msg) ||
     144          90 :             wps_build_encr_type_flags(wps, msg) ||
     145          90 :             wps_build_conn_type_flags(wps, msg) ||
     146          90 :             wps_build_config_methods(msg, config_methods) ||
     147          90 :             wps_build_wps_state(wps, msg) ||
     148          90 :             wps_build_device_attrs(&wps->wps->dev, msg) ||
     149          45 :             wps_build_rf_bands(&wps->wps->dev, msg,
     150          90 :                                wps->wps->rf_band_cb(wps->wps->cb_ctx)) ||
     151          90 :             wps_build_assoc_state(wps, msg) ||
     152          90 :             wps_build_dev_password_id(msg, wps->dev_pw_id) ||
     153          90 :             wps_build_config_error(msg, WPS_CFG_NO_ERROR) ||
     154          90 :             wps_build_os_version(&wps->wps->dev, msg) ||
     155          90 :             wps_build_wfa_ext(msg, 0, NULL, 0) ||
     156          45 :             wps_build_vendor_ext_m1(&wps->wps->dev, msg)) {
     157           0 :                 wpabuf_free(msg);
     158           0 :                 return NULL;
     159             :         }
     160             : 
     161          45 :         wps->state = RECV_M2;
     162          45 :         return msg;
     163             : }
     164             : 
     165             : 
     166          29 : static struct wpabuf * wps_build_m3(struct wps_data *wps)
     167             : {
     168             :         struct wpabuf *msg;
     169             : 
     170          29 :         wpa_printf(MSG_DEBUG, "WPS: Building Message M3");
     171             : 
     172          29 :         if (wps->dev_password == NULL) {
     173           0 :                 wpa_printf(MSG_DEBUG, "WPS: No Device Password available");
     174           0 :                 return NULL;
     175             :         }
     176          29 :         wps_derive_psk(wps, wps->dev_password, wps->dev_password_len);
     177             : 
     178             :         if (wps->wps->ap && random_pool_ready() != 1) {
     179             :                 wpa_printf(MSG_INFO,
     180             :                            "WPS: Not enough entropy in random pool to proceed - do not allow AP PIN to be used");
     181             :                 return NULL;
     182             :         }
     183             : 
     184          29 :         msg = wpabuf_alloc(1000);
     185          29 :         if (msg == NULL)
     186           0 :                 return NULL;
     187             : 
     188          58 :         if (wps_build_version(msg) ||
     189          58 :             wps_build_msg_type(msg, WPS_M3) ||
     190          58 :             wps_build_registrar_nonce(wps, msg) ||
     191          58 :             wps_build_e_hash(wps, msg) ||
     192          58 :             wps_build_wfa_ext(msg, 0, NULL, 0) ||
     193          29 :             wps_build_authenticator(wps, msg)) {
     194           0 :                 wpabuf_free(msg);
     195           0 :                 return NULL;
     196             :         }
     197             : 
     198          29 :         wps->state = RECV_M4;
     199          29 :         return msg;
     200             : }
     201             : 
     202             : 
     203          25 : static struct wpabuf * wps_build_m5(struct wps_data *wps)
     204             : {
     205             :         struct wpabuf *msg, *plain;
     206             : 
     207          25 :         wpa_printf(MSG_DEBUG, "WPS: Building Message M5");
     208             : 
     209          25 :         plain = wpabuf_alloc(200);
     210          25 :         if (plain == NULL)
     211           0 :                 return NULL;
     212             : 
     213          25 :         msg = wpabuf_alloc(1000);
     214          25 :         if (msg == NULL) {
     215           0 :                 wpabuf_free(plain);
     216           0 :                 return NULL;
     217             :         }
     218             : 
     219          50 :         if (wps_build_version(msg) ||
     220          50 :             wps_build_msg_type(msg, WPS_M5) ||
     221          50 :             wps_build_registrar_nonce(wps, msg) ||
     222          50 :             wps_build_e_snonce1(wps, plain) ||
     223          50 :             wps_build_key_wrap_auth(wps, plain) ||
     224          50 :             wps_build_encr_settings(wps, msg, plain) ||
     225          50 :             wps_build_wfa_ext(msg, 0, NULL, 0) ||
     226          25 :             wps_build_authenticator(wps, msg)) {
     227           0 :                 wpabuf_free(plain);
     228           0 :                 wpabuf_free(msg);
     229           0 :                 return NULL;
     230             :         }
     231          25 :         wpabuf_free(plain);
     232             : 
     233          25 :         wps->state = RECV_M6;
     234          25 :         return msg;
     235             : }
     236             : 
     237             : 
     238          23 : static int wps_build_cred_ssid(struct wps_data *wps, struct wpabuf *msg)
     239             : {
     240          23 :         wpa_printf(MSG_DEBUG, "WPS:  * SSID");
     241          23 :         wpabuf_put_be16(msg, ATTR_SSID);
     242          23 :         wpabuf_put_be16(msg, wps->wps->ssid_len);
     243          23 :         wpabuf_put_data(msg, wps->wps->ssid, wps->wps->ssid_len);
     244          23 :         return 0;
     245             : }
     246             : 
     247             : 
     248          23 : static int wps_build_cred_auth_type(struct wps_data *wps, struct wpabuf *msg)
     249             : {
     250          23 :         wpa_printf(MSG_DEBUG, "WPS:  * Authentication Type (0x%x)",
     251          23 :                    wps->wps->ap_auth_type);
     252          23 :         wpabuf_put_be16(msg, ATTR_AUTH_TYPE);
     253          23 :         wpabuf_put_be16(msg, 2);
     254          23 :         wpabuf_put_be16(msg, wps->wps->ap_auth_type);
     255          23 :         return 0;
     256             : }
     257             : 
     258             : 
     259          23 : static int wps_build_cred_encr_type(struct wps_data *wps, struct wpabuf *msg)
     260             : {
     261          23 :         wpa_printf(MSG_DEBUG, "WPS:  * Encryption Type (0x%x)",
     262          23 :                    wps->wps->ap_encr_type);
     263          23 :         wpabuf_put_be16(msg, ATTR_ENCR_TYPE);
     264          23 :         wpabuf_put_be16(msg, 2);
     265          23 :         wpabuf_put_be16(msg, wps->wps->ap_encr_type);
     266          23 :         return 0;
     267             : }
     268             : 
     269             : 
     270          23 : static int wps_build_cred_network_key(struct wps_data *wps, struct wpabuf *msg)
     271             : {
     272          40 :         if ((wps->wps->ap_auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) &&
     273          17 :             wps->wps->network_key_len == 0) {
     274             :                 char hex[65];
     275             :                 u8 psk[32];
     276             :                 /* Generate a random per-device PSK */
     277           3 :                 if (random_pool_ready() != 1 ||
     278           3 :                     random_get_bytes(psk, sizeof(psk)) < 0) {
     279           0 :                         wpa_printf(MSG_INFO,
     280             :                                    "WPS: Could not generate random PSK");
     281           0 :                         return -1;
     282             :                 }
     283           3 :                 wpa_hexdump_key(MSG_DEBUG, "WPS: Generated per-device PSK",
     284             :                                 psk, sizeof(psk));
     285           3 :                 wpa_printf(MSG_DEBUG, "WPS:  * Network Key (len=%u)",
     286           3 :                            (unsigned int) wps->new_psk_len * 2);
     287           3 :                 wpa_snprintf_hex(hex, sizeof(hex), psk, sizeof(psk));
     288           3 :                 wpabuf_put_be16(msg, ATTR_NETWORK_KEY);
     289           3 :                 wpabuf_put_be16(msg, sizeof(psk) * 2);
     290           3 :                 wpabuf_put_data(msg, hex, sizeof(psk) * 2);
     291           3 :                 if (wps->wps->registrar) {
     292           3 :                         wps_cb_new_psk(wps->wps->registrar,
     293           3 :                                        wps->peer_dev.mac_addr,
     294           3 :                                        wps->p2p_dev_addr, psk, sizeof(psk));
     295             :                 }
     296           3 :                 return 0;
     297             :         }
     298             : 
     299          20 :         wpa_printf(MSG_DEBUG, "WPS:  * Network Key (len=%u)",
     300          20 :                    (unsigned int) wps->wps->network_key_len);
     301          20 :         wpabuf_put_be16(msg, ATTR_NETWORK_KEY);
     302          20 :         wpabuf_put_be16(msg, wps->wps->network_key_len);
     303          20 :         wpabuf_put_data(msg, wps->wps->network_key, wps->wps->network_key_len);
     304          20 :         return 0;
     305             : }
     306             : 
     307             : 
     308          23 : static int wps_build_cred_mac_addr(struct wps_data *wps, struct wpabuf *msg)
     309             : {
     310          23 :         wpa_printf(MSG_DEBUG, "WPS:  * MAC Address (AP BSSID)");
     311          23 :         wpabuf_put_be16(msg, ATTR_MAC_ADDR);
     312          23 :         wpabuf_put_be16(msg, ETH_ALEN);
     313          23 :         wpabuf_put_data(msg, wps->wps->dev.mac_addr, ETH_ALEN);
     314          23 :         return 0;
     315             : }
     316             : 
     317             : 
     318          23 : static int wps_build_ap_settings(struct wps_data *wps, struct wpabuf *plain)
     319             : {
     320             :         const u8 *start, *end;
     321             :         int ret;
     322             : 
     323          23 :         if (wps->wps->ap_settings) {
     324           0 :                 wpa_printf(MSG_DEBUG, "WPS:  * AP Settings (pre-configured)");
     325           0 :                 wpabuf_put_data(plain, wps->wps->ap_settings,
     326           0 :                                 wps->wps->ap_settings_len);
     327           0 :                 return 0;
     328             :         }
     329             : 
     330          23 :         wpa_printf(MSG_DEBUG, "WPS:  * AP Settings based on current configuration");
     331          23 :         start = wpabuf_put(plain, 0);
     332          69 :         ret = wps_build_cred_ssid(wps, plain) ||
     333          46 :                 wps_build_cred_mac_addr(wps, plain) ||
     334          46 :                 wps_build_cred_auth_type(wps, plain) ||
     335          69 :                 wps_build_cred_encr_type(wps, plain) ||
     336          23 :                 wps_build_cred_network_key(wps, plain);
     337          23 :         end = wpabuf_put(plain, 0);
     338             : 
     339          23 :         wpa_hexdump_key(MSG_DEBUG, "WPS: Plaintext AP Settings",
     340          23 :                         start, end - start);
     341             : 
     342          23 :         return ret;
     343             : }
     344             : 
     345             : 
     346          23 : static struct wpabuf * wps_build_m7(struct wps_data *wps)
     347             : {
     348             :         struct wpabuf *msg, *plain;
     349             : 
     350          23 :         wpa_printf(MSG_DEBUG, "WPS: Building Message M7");
     351             : 
     352          23 :         plain = wpabuf_alloc(500 + wps->wps->ap_settings_len);
     353          23 :         if (plain == NULL)
     354           0 :                 return NULL;
     355             : 
     356          23 :         msg = wpabuf_alloc(1000 + wps->wps->ap_settings_len);
     357          23 :         if (msg == NULL) {
     358           0 :                 wpabuf_free(plain);
     359           0 :                 return NULL;
     360             :         }
     361             : 
     362          46 :         if (wps_build_version(msg) ||
     363          46 :             wps_build_msg_type(msg, WPS_M7) ||
     364          46 :             wps_build_registrar_nonce(wps, msg) ||
     365          46 :             wps_build_e_snonce2(wps, plain) ||
     366          69 :             (wps->wps->ap && wps_build_ap_settings(wps, plain)) ||
     367          46 :             wps_build_key_wrap_auth(wps, plain) ||
     368          46 :             wps_build_encr_settings(wps, msg, plain) ||
     369          46 :             wps_build_wfa_ext(msg, 0, NULL, 0) ||
     370          23 :             wps_build_authenticator(wps, msg)) {
     371           0 :                 wpabuf_free(plain);
     372           0 :                 wpabuf_free(msg);
     373           0 :                 return NULL;
     374             :         }
     375          23 :         wpabuf_free(plain);
     376             : 
     377          23 :         if (wps->wps->ap && wps->wps->registrar) {
     378             :                 /*
     379             :                  * If the Registrar is only learning our current configuration,
     380             :                  * it may not continue protocol run to successful completion.
     381             :                  * Store information here to make sure it remains available.
     382             :                  */
     383          23 :                 wps_device_store(wps->wps->registrar, &wps->peer_dev,
     384          23 :                                  wps->uuid_r);
     385             :         }
     386             : 
     387          23 :         wps->state = RECV_M8;
     388          23 :         return msg;
     389             : }
     390             : 
     391             : 
     392           7 : static struct wpabuf * wps_build_wsc_done(struct wps_data *wps)
     393             : {
     394             :         struct wpabuf *msg;
     395             : 
     396           7 :         wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_Done");
     397             : 
     398           7 :         msg = wpabuf_alloc(1000);
     399           7 :         if (msg == NULL)
     400           0 :                 return NULL;
     401             : 
     402          14 :         if (wps_build_version(msg) ||
     403          14 :             wps_build_msg_type(msg, WPS_WSC_DONE) ||
     404          14 :             wps_build_enrollee_nonce(wps, msg) ||
     405          14 :             wps_build_registrar_nonce(wps, msg) ||
     406           7 :             wps_build_wfa_ext(msg, 0, NULL, 0)) {
     407           0 :                 wpabuf_free(msg);
     408           0 :                 return NULL;
     409             :         }
     410             : 
     411           7 :         if (wps->wps->ap)
     412           7 :                 wps->state = RECV_ACK;
     413             :         else {
     414           0 :                 wps_success_event(wps->wps, wps->peer_dev.mac_addr);
     415           0 :                 wps->state = WPS_FINISHED;
     416             :         }
     417           7 :         return msg;
     418             : }
     419             : 
     420             : 
     421         142 : struct wpabuf * wps_enrollee_get_msg(struct wps_data *wps,
     422             :                                      enum wsc_op_code *op_code)
     423             : {
     424             :         struct wpabuf *msg;
     425             : 
     426         142 :         switch (wps->state) {
     427             :         case SEND_M1:
     428          45 :                 msg = wps_build_m1(wps);
     429          45 :                 *op_code = WSC_MSG;
     430          45 :                 break;
     431             :         case SEND_M3:
     432          29 :                 msg = wps_build_m3(wps);
     433          29 :                 *op_code = WSC_MSG;
     434          29 :                 break;
     435             :         case SEND_M5:
     436          25 :                 msg = wps_build_m5(wps);
     437          25 :                 *op_code = WSC_MSG;
     438          25 :                 break;
     439             :         case SEND_M7:
     440          23 :                 msg = wps_build_m7(wps);
     441          23 :                 *op_code = WSC_MSG;
     442          23 :                 break;
     443             :         case RECEIVED_M2D:
     444           0 :                 if (wps->wps->ap) {
     445           0 :                         msg = wps_build_wsc_nack(wps);
     446           0 :                         *op_code = WSC_NACK;
     447           0 :                         break;
     448             :                 }
     449           0 :                 msg = wps_build_wsc_ack(wps);
     450           0 :                 *op_code = WSC_ACK;
     451           0 :                 if (msg) {
     452             :                         /* Another M2/M2D may be received */
     453           0 :                         wps->state = RECV_M2;
     454             :                 }
     455           0 :                 break;
     456             :         case SEND_WSC_NACK:
     457          13 :                 msg = wps_build_wsc_nack(wps);
     458          13 :                 *op_code = WSC_NACK;
     459          13 :                 break;
     460             :         case WPS_MSG_DONE:
     461           7 :                 msg = wps_build_wsc_done(wps);
     462           7 :                 *op_code = WSC_Done;
     463           7 :                 break;
     464             :         default:
     465           0 :                 wpa_printf(MSG_DEBUG, "WPS: Unsupported state %d for building "
     466           0 :                            "a message", wps->state);
     467           0 :                 msg = NULL;
     468           0 :                 break;
     469             :         }
     470             : 
     471         142 :         if (*op_code == WSC_MSG && msg) {
     472             :                 /* Save a copy of the last message for Authenticator derivation
     473             :                  */
     474         122 :                 wpabuf_free(wps->last_msg);
     475         122 :                 wps->last_msg = wpabuf_dup(msg);
     476             :         }
     477             : 
     478         142 :         return msg;
     479             : }
     480             : 
     481             : 
     482          35 : static int wps_process_registrar_nonce(struct wps_data *wps, const u8 *r_nonce)
     483             : {
     484          35 :         if (r_nonce == NULL) {
     485           0 :                 wpa_printf(MSG_DEBUG, "WPS: No Registrar Nonce received");
     486           0 :                 return -1;
     487             :         }
     488             : 
     489          35 :         os_memcpy(wps->nonce_r, r_nonce, WPS_NONCE_LEN);
     490          35 :         wpa_hexdump(MSG_DEBUG, "WPS: Registrar Nonce",
     491          35 :                     wps->nonce_r, WPS_NONCE_LEN);
     492             : 
     493          35 :         return 0;
     494             : }
     495             : 
     496             : 
     497          97 : static int wps_process_enrollee_nonce(struct wps_data *wps, const u8 *e_nonce)
     498             : {
     499          97 :         if (e_nonce == NULL) {
     500           0 :                 wpa_printf(MSG_DEBUG, "WPS: No Enrollee Nonce received");
     501           0 :                 return -1;
     502             :         }
     503             : 
     504          97 :         if (os_memcmp(wps->nonce_e, e_nonce, WPS_NONCE_LEN) != 0) {
     505           0 :                 wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce received");
     506           0 :                 return -1;
     507             :         }
     508             : 
     509          97 :         return 0;
     510             : }
     511             : 
     512             : 
     513          35 : static int wps_process_uuid_r(struct wps_data *wps, const u8 *uuid_r)
     514             : {
     515          35 :         if (uuid_r == NULL) {
     516           0 :                 wpa_printf(MSG_DEBUG, "WPS: No UUID-R received");
     517           0 :                 return -1;
     518             :         }
     519             : 
     520          35 :         os_memcpy(wps->uuid_r, uuid_r, WPS_UUID_LEN);
     521          35 :         wpa_hexdump(MSG_DEBUG, "WPS: UUID-R", wps->uuid_r, WPS_UUID_LEN);
     522             : 
     523          35 :         return 0;
     524             : }
     525             : 
     526             : 
     527          29 : static int wps_process_pubkey(struct wps_data *wps, const u8 *pk,
     528             :                               size_t pk_len)
     529             : {
     530          29 :         if (pk == NULL || pk_len == 0) {
     531           0 :                 wpa_printf(MSG_DEBUG, "WPS: No Public Key received");
     532           0 :                 return -1;
     533             :         }
     534             : 
     535          29 :         if (wps->peer_pubkey_hash_set) {
     536             :                 u8 hash[WPS_HASH_LEN];
     537           0 :                 sha256_vector(1, &pk, &pk_len, hash);
     538           0 :                 if (os_memcmp_const(hash, wps->peer_pubkey_hash,
     539             :                                     WPS_OOB_PUBKEY_HASH_LEN) != 0) {
     540           0 :                         wpa_printf(MSG_ERROR, "WPS: Public Key hash mismatch");
     541           0 :                         wpa_hexdump(MSG_DEBUG, "WPS: Received public key",
     542             :                                     pk, pk_len);
     543           0 :                         wpa_hexdump(MSG_DEBUG, "WPS: Calculated public key "
     544             :                                     "hash", hash, WPS_OOB_PUBKEY_HASH_LEN);
     545           0 :                         wpa_hexdump(MSG_DEBUG, "WPS: Expected public key hash",
     546           0 :                                     wps->peer_pubkey_hash,
     547             :                                     WPS_OOB_PUBKEY_HASH_LEN);
     548           0 :                         wps->config_error = WPS_CFG_PUBLIC_KEY_HASH_MISMATCH;
     549           0 :                         return -1;
     550             :                 }
     551             :         }
     552             : 
     553          29 :         wpabuf_free(wps->dh_pubkey_r);
     554          29 :         wps->dh_pubkey_r = wpabuf_alloc_copy(pk, pk_len);
     555          29 :         if (wps->dh_pubkey_r == NULL)
     556           0 :                 return -1;
     557             : 
     558          29 :         if (wps_derive_keys(wps) < 0)
     559           0 :                 return -1;
     560             : 
     561          29 :         return 0;
     562             : }
     563             : 
     564             : 
     565          29 : static int wps_process_r_hash1(struct wps_data *wps, const u8 *r_hash1)
     566             : {
     567          29 :         if (r_hash1 == NULL) {
     568           0 :                 wpa_printf(MSG_DEBUG, "WPS: No R-Hash1 received");
     569           0 :                 return -1;
     570             :         }
     571             : 
     572          29 :         os_memcpy(wps->peer_hash1, r_hash1, WPS_HASH_LEN);
     573          29 :         wpa_hexdump(MSG_DEBUG, "WPS: R-Hash1", wps->peer_hash1, WPS_HASH_LEN);
     574             : 
     575          29 :         return 0;
     576             : }
     577             : 
     578             : 
     579          29 : static int wps_process_r_hash2(struct wps_data *wps, const u8 *r_hash2)
     580             : {
     581          29 :         if (r_hash2 == NULL) {
     582           0 :                 wpa_printf(MSG_DEBUG, "WPS: No R-Hash2 received");
     583           0 :                 return -1;
     584             :         }
     585             : 
     586          29 :         os_memcpy(wps->peer_hash2, r_hash2, WPS_HASH_LEN);
     587          29 :         wpa_hexdump(MSG_DEBUG, "WPS: R-Hash2", wps->peer_hash2, WPS_HASH_LEN);
     588             : 
     589          29 :         return 0;
     590             : }
     591             : 
     592             : 
     593          29 : static int wps_process_r_snonce1(struct wps_data *wps, const u8 *r_snonce1)
     594             : {
     595             :         u8 hash[SHA256_MAC_LEN];
     596             :         const u8 *addr[4];
     597             :         size_t len[4];
     598             : 
     599          29 :         if (r_snonce1 == NULL) {
     600           0 :                 wpa_printf(MSG_DEBUG, "WPS: No R-SNonce1 received");
     601           0 :                 return -1;
     602             :         }
     603             : 
     604          29 :         wpa_hexdump_key(MSG_DEBUG, "WPS: R-SNonce1", r_snonce1,
     605             :                         WPS_SECRET_NONCE_LEN);
     606             : 
     607             :         /* R-Hash1 = HMAC_AuthKey(R-S1 || PSK1 || PK_E || PK_R) */
     608          29 :         addr[0] = r_snonce1;
     609          29 :         len[0] = WPS_SECRET_NONCE_LEN;
     610          29 :         addr[1] = wps->psk1;
     611          29 :         len[1] = WPS_PSK_LEN;
     612          29 :         addr[2] = wpabuf_head(wps->dh_pubkey_e);
     613          29 :         len[2] = wpabuf_len(wps->dh_pubkey_e);
     614          29 :         addr[3] = wpabuf_head(wps->dh_pubkey_r);
     615          29 :         len[3] = wpabuf_len(wps->dh_pubkey_r);
     616          29 :         hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
     617             : 
     618          29 :         if (os_memcmp_const(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) {
     619           4 :                 wpa_printf(MSG_DEBUG, "WPS: R-Hash1 derived from R-S1 does "
     620             :                            "not match with the pre-committed value");
     621           4 :                 wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE;
     622           4 :                 wps_pwd_auth_fail_event(wps->wps, 1, 1, wps->peer_dev.mac_addr);
     623           4 :                 return -1;
     624             :         }
     625             : 
     626          25 :         wpa_printf(MSG_DEBUG, "WPS: Registrar proved knowledge of the first "
     627             :                    "half of the device password");
     628             : 
     629          25 :         return 0;
     630             : }
     631             : 
     632             : 
     633          25 : static int wps_process_r_snonce2(struct wps_data *wps, const u8 *r_snonce2)
     634             : {
     635             :         u8 hash[SHA256_MAC_LEN];
     636             :         const u8 *addr[4];
     637             :         size_t len[4];
     638             : 
     639          25 :         if (r_snonce2 == NULL) {
     640           0 :                 wpa_printf(MSG_DEBUG, "WPS: No R-SNonce2 received");
     641           0 :                 return -1;
     642             :         }
     643             : 
     644          25 :         wpa_hexdump_key(MSG_DEBUG, "WPS: R-SNonce2", r_snonce2,
     645             :                         WPS_SECRET_NONCE_LEN);
     646             : 
     647             :         /* R-Hash2 = HMAC_AuthKey(R-S2 || PSK2 || PK_E || PK_R) */
     648          25 :         addr[0] = r_snonce2;
     649          25 :         len[0] = WPS_SECRET_NONCE_LEN;
     650          25 :         addr[1] = wps->psk2;
     651          25 :         len[1] = WPS_PSK_LEN;
     652          25 :         addr[2] = wpabuf_head(wps->dh_pubkey_e);
     653          25 :         len[2] = wpabuf_len(wps->dh_pubkey_e);
     654          25 :         addr[3] = wpabuf_head(wps->dh_pubkey_r);
     655          25 :         len[3] = wpabuf_len(wps->dh_pubkey_r);
     656          25 :         hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
     657             : 
     658          25 :         if (os_memcmp_const(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) {
     659           2 :                 wpa_printf(MSG_DEBUG, "WPS: R-Hash2 derived from R-S2 does "
     660             :                            "not match with the pre-committed value");
     661           2 :                 wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE;
     662           2 :                 wps_pwd_auth_fail_event(wps->wps, 1, 2, wps->peer_dev.mac_addr);
     663           2 :                 return -1;
     664             :         }
     665             : 
     666          23 :         wpa_printf(MSG_DEBUG, "WPS: Registrar proved knowledge of the second "
     667             :                    "half of the device password");
     668             : 
     669          23 :         return 0;
     670             : }
     671             : 
     672             : 
     673           0 : static int wps_process_cred_e(struct wps_data *wps, const u8 *cred,
     674             :                               size_t cred_len, int wps2)
     675             : {
     676             :         struct wps_parse_attr attr;
     677             :         struct wpabuf msg;
     678           0 :         int ret = 0;
     679             : 
     680           0 :         wpa_printf(MSG_DEBUG, "WPS: Received Credential");
     681           0 :         os_memset(&wps->cred, 0, sizeof(wps->cred));
     682           0 :         wpabuf_set(&msg, cred, cred_len);
     683           0 :         if (wps_parse_msg(&msg, &attr) < 0 ||
     684           0 :             wps_process_cred(&attr, &wps->cred))
     685           0 :                 return -1;
     686             : 
     687           0 :         if (os_memcmp(wps->cred.mac_addr, wps->wps->dev.mac_addr, ETH_ALEN) !=
     688             :             0) {
     689           0 :                 wpa_printf(MSG_DEBUG, "WPS: MAC Address in the Credential ("
     690             :                            MACSTR ") does not match with own address (" MACSTR
     691           0 :                            ")", MAC2STR(wps->cred.mac_addr),
     692           0 :                            MAC2STR(wps->wps->dev.mac_addr));
     693             :                 /*
     694             :                  * In theory, this could be consider fatal error, but there are
     695             :                  * number of deployed implementations using other address here
     696             :                  * due to unclarity in the specification. For interoperability
     697             :                  * reasons, allow this to be processed since we do not really
     698             :                  * use the MAC Address information for anything.
     699             :                  */
     700             : #ifdef CONFIG_WPS_STRICT
     701             :                 if (wps2) {
     702             :                         wpa_printf(MSG_INFO, "WPS: Do not accept incorrect "
     703             :                                    "MAC Address in AP Settings");
     704             :                         return -1;
     705             :                 }
     706             : #endif /* CONFIG_WPS_STRICT */
     707             :         }
     708             : 
     709           0 :         if (!(wps->cred.encr_type &
     710             :               (WPS_ENCR_NONE | WPS_ENCR_TKIP | WPS_ENCR_AES))) {
     711           0 :                 if (wps->cred.encr_type & WPS_ENCR_WEP) {
     712           0 :                         wpa_printf(MSG_INFO, "WPS: Reject Credential "
     713             :                                    "due to WEP configuration");
     714           0 :                         wps->error_indication = WPS_EI_SECURITY_WEP_PROHIBITED;
     715           0 :                         return -2;
     716             :                 }
     717             : 
     718           0 :                 wpa_printf(MSG_INFO, "WPS: Reject Credential due to "
     719           0 :                            "invalid encr_type 0x%x", wps->cred.encr_type);
     720           0 :                 return -1;
     721             :         }
     722             : 
     723           0 :         if (wps->wps->cred_cb) {
     724           0 :                 wps->cred.cred_attr = cred - 4;
     725           0 :                 wps->cred.cred_attr_len = cred_len + 4;
     726           0 :                 ret = wps->wps->cred_cb(wps->wps->cb_ctx, &wps->cred);
     727           0 :                 wps->cred.cred_attr = NULL;
     728           0 :                 wps->cred.cred_attr_len = 0;
     729             :         }
     730             : 
     731           0 :         return ret;
     732             : }
     733             : 
     734             : 
     735           8 : static int wps_process_creds(struct wps_data *wps, const u8 *cred[],
     736             :                              size_t cred_len[], size_t num_cred, int wps2)
     737             : {
     738             :         size_t i;
     739           8 :         int ok = 0;
     740             : 
     741           8 :         if (wps->wps->ap)
     742           8 :                 return 0;
     743             : 
     744           0 :         if (num_cred == 0) {
     745           0 :                 wpa_printf(MSG_DEBUG, "WPS: No Credential attributes "
     746             :                            "received");
     747           0 :                 return -1;
     748             :         }
     749             : 
     750           0 :         for (i = 0; i < num_cred; i++) {
     751             :                 int res;
     752           0 :                 res = wps_process_cred_e(wps, cred[i], cred_len[i], wps2);
     753           0 :                 if (res == 0)
     754           0 :                         ok++;
     755           0 :                 else if (res == -2)
     756           0 :                         wpa_printf(MSG_DEBUG, "WPS: WEP credential skipped");
     757             :                 else
     758           0 :                         return -1;
     759             :         }
     760             : 
     761           0 :         if (ok == 0) {
     762           0 :                 wpa_printf(MSG_DEBUG, "WPS: No valid Credential attribute "
     763             :                            "received");
     764           0 :                 return -1;
     765             :         }
     766             : 
     767           0 :         return 0;
     768             : }
     769             : 
     770             : 
     771           8 : static int wps_process_ap_settings_e(struct wps_data *wps,
     772             :                                      struct wps_parse_attr *attr,
     773             :                                      struct wpabuf *attrs, int wps2)
     774             : {
     775             :         struct wps_credential cred;
     776             : 
     777           8 :         if (!wps->wps->ap)
     778           0 :                 return 0;
     779             : 
     780           8 :         if (wps_process_ap_settings(attr, &cred) < 0)
     781           0 :                 return -1;
     782             : 
     783           8 :         wpa_printf(MSG_INFO, "WPS: Received new AP configuration from "
     784             :                    "Registrar");
     785             : 
     786           8 :         if (os_memcmp(cred.mac_addr, wps->wps->dev.mac_addr, ETH_ALEN) !=
     787             :             0) {
     788           0 :                 wpa_printf(MSG_DEBUG, "WPS: MAC Address in the AP Settings ("
     789             :                            MACSTR ") does not match with own address (" MACSTR
     790           0 :                            ")", MAC2STR(cred.mac_addr),
     791           0 :                            MAC2STR(wps->wps->dev.mac_addr));
     792             :                 /*
     793             :                  * In theory, this could be consider fatal error, but there are
     794             :                  * number of deployed implementations using other address here
     795             :                  * due to unclarity in the specification. For interoperability
     796             :                  * reasons, allow this to be processed since we do not really
     797             :                  * use the MAC Address information for anything.
     798             :                  */
     799             : #ifdef CONFIG_WPS_STRICT
     800             :                 if (wps2) {
     801             :                         wpa_printf(MSG_INFO, "WPS: Do not accept incorrect "
     802             :                                    "MAC Address in AP Settings");
     803             :                         return -1;
     804             :                 }
     805             : #endif /* CONFIG_WPS_STRICT */
     806             :         }
     807             : 
     808           8 :         if (!(cred.encr_type & (WPS_ENCR_NONE | WPS_ENCR_TKIP | WPS_ENCR_AES)))
     809             :         {
     810           1 :                 if (cred.encr_type & WPS_ENCR_WEP) {
     811           1 :                         wpa_printf(MSG_INFO, "WPS: Reject new AP settings "
     812             :                                    "due to WEP configuration");
     813           1 :                         wps->error_indication = WPS_EI_SECURITY_WEP_PROHIBITED;
     814           1 :                         return -1;
     815             :                 }
     816             : 
     817           0 :                 wpa_printf(MSG_INFO, "WPS: Reject new AP settings due to "
     818           0 :                            "invalid encr_type 0x%x", cred.encr_type);
     819           0 :                 return -1;
     820             :         }
     821             : 
     822             : #ifdef CONFIG_WPS_STRICT
     823             :         if (wps2) {
     824             :                 if ((cred.encr_type & (WPS_ENCR_TKIP | WPS_ENCR_AES)) ==
     825             :                     WPS_ENCR_TKIP ||
     826             :                     (cred.auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) ==
     827             :                     WPS_AUTH_WPAPSK) {
     828             :                         wpa_printf(MSG_INFO, "WPS-STRICT: Invalid WSC 2.0 "
     829             :                                    "AP Settings: WPA-Personal/TKIP only");
     830             :                         wps->error_indication =
     831             :                                 WPS_EI_SECURITY_TKIP_ONLY_PROHIBITED;
     832             :                         return -1;
     833             :                 }
     834             :         }
     835             : #endif /* CONFIG_WPS_STRICT */
     836             : 
     837           7 :         if ((cred.encr_type & (WPS_ENCR_TKIP | WPS_ENCR_AES)) == WPS_ENCR_TKIP)
     838             :         {
     839           1 :                 wpa_printf(MSG_DEBUG, "WPS: Upgrade encr_type TKIP -> "
     840             :                            "TKIP+AES");
     841           1 :                 cred.encr_type |= WPS_ENCR_AES;
     842             :         }
     843             : 
     844           7 :         if ((cred.auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) ==
     845             :             WPS_AUTH_WPAPSK) {
     846           1 :                 wpa_printf(MSG_DEBUG, "WPS: Upgrade auth_type WPAPSK -> "
     847             :                            "WPAPSK+WPA2PSK");
     848           1 :                 cred.auth_type |= WPS_AUTH_WPA2PSK;
     849             :         }
     850             : 
     851           7 :         if (wps->wps->cred_cb) {
     852           7 :                 cred.cred_attr = wpabuf_head(attrs);
     853           7 :                 cred.cred_attr_len = wpabuf_len(attrs);
     854           7 :                 wps->wps->cred_cb(wps->wps->cb_ctx, &cred);
     855             :         }
     856             : 
     857           7 :         return 0;
     858             : }
     859             : 
     860             : 
     861          35 : static int wps_process_dev_pw_id(struct wps_data *wps, const u8 *dev_pw_id)
     862             : {
     863             :         u16 id;
     864             : 
     865          35 :         if (dev_pw_id == NULL) {
     866           0 :                 wpa_printf(MSG_DEBUG, "WPS: Device Password ID");
     867           0 :                 return -1;
     868             :         }
     869             : 
     870          35 :         id = WPA_GET_BE16(dev_pw_id);
     871          35 :         if (wps->dev_pw_id == id) {
     872          35 :                 wpa_printf(MSG_DEBUG, "WPS: Device Password ID %u", id);
     873          35 :                 return 0;
     874             :         }
     875             : 
     876             : #ifdef CONFIG_P2P
     877             :         if ((id == DEV_PW_DEFAULT &&
     878             :              wps->dev_pw_id == DEV_PW_REGISTRAR_SPECIFIED) ||
     879             :             (id == DEV_PW_REGISTRAR_SPECIFIED &&
     880             :              wps->dev_pw_id == DEV_PW_DEFAULT)) {
     881             :                 /*
     882             :                  * Common P2P use cases indicate whether the PIN is from the
     883             :                  * client or GO using Device Password Id in M1/M2 in a way that
     884             :                  * does not look fully compliant with WSC specification. Anyway,
     885             :                  * this is deployed and needs to be allowed, so ignore changes
     886             :                  * between Registrar-Specified and Default PIN.
     887             :                  */
     888             :                 wpa_printf(MSG_DEBUG, "WPS: Allow PIN Device Password ID "
     889             :                            "change");
     890             :                 return 0;
     891             :         }
     892             : #endif /* CONFIG_P2P */
     893             : 
     894           0 :         wpa_printf(MSG_DEBUG, "WPS: Registrar trying to change Device Password "
     895           0 :                    "ID from %u to %u", wps->dev_pw_id, id);
     896             : 
     897           0 :         if (wps->dev_pw_id == DEV_PW_PUSHBUTTON && id == DEV_PW_DEFAULT) {
     898           0 :                 wpa_printf(MSG_DEBUG,
     899             :                            "WPS: Workaround - ignore PBC-to-PIN change");
     900           0 :                 return 0;
     901             :         }
     902             : 
     903           0 :         if (wps->alt_dev_password && wps->alt_dev_pw_id == id) {
     904           0 :                 wpa_printf(MSG_DEBUG, "WPS: Found a matching Device Password");
     905           0 :                 bin_clear_free(wps->dev_password, wps->dev_password_len);
     906           0 :                 wps->dev_pw_id = wps->alt_dev_pw_id;
     907           0 :                 wps->dev_password = wps->alt_dev_password;
     908           0 :                 wps->dev_password_len = wps->alt_dev_password_len;
     909           0 :                 wps->alt_dev_password = NULL;
     910           0 :                 wps->alt_dev_password_len = 0;
     911           0 :                 return 0;
     912             :         }
     913             : 
     914           0 :         return -1;
     915             : }
     916             : 
     917             : 
     918          35 : static enum wps_process_res wps_process_m2(struct wps_data *wps,
     919             :                                            const struct wpabuf *msg,
     920             :                                            struct wps_parse_attr *attr)
     921             : {
     922          35 :         wpa_printf(MSG_DEBUG, "WPS: Received M2");
     923             : 
     924          35 :         if (wps->state != RECV_M2) {
     925           0 :                 wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
     926           0 :                            "receiving M2", wps->state);
     927           0 :                 wps->state = SEND_WSC_NACK;
     928           0 :                 return WPS_CONTINUE;
     929             :         }
     930             : 
     931          70 :         if (wps_process_registrar_nonce(wps, attr->registrar_nonce) ||
     932          70 :             wps_process_enrollee_nonce(wps, attr->enrollee_nonce) ||
     933          70 :             wps_process_uuid_r(wps, attr->uuid_r) ||
     934          35 :             wps_process_dev_pw_id(wps, attr->dev_password_id)) {
     935           0 :                 wps->state = SEND_WSC_NACK;
     936           0 :                 return WPS_CONTINUE;
     937             :         }
     938             : 
     939             :         /*
     940             :          * Stop here on an AP as an Enrollee if AP Setup is locked unless the
     941             :          * special locked mode is used to allow protocol run up to M7 in order
     942             :          * to support external Registrars that only learn the current AP
     943             :          * configuration without changing it.
     944             :          */
     945          70 :         if (wps->wps->ap &&
     946          70 :             ((wps->wps->ap_setup_locked && wps->wps->ap_setup_locked != 2) ||
     947          32 :              wps->dev_password == NULL)) {
     948           6 :                 wpa_printf(MSG_DEBUG, "WPS: AP Setup is locked - refuse "
     949             :                            "registration of a new Registrar");
     950           6 :                 wps->config_error = WPS_CFG_SETUP_LOCKED;
     951           6 :                 wps->state = SEND_WSC_NACK;
     952           6 :                 return WPS_CONTINUE;
     953             :         }
     954             : 
     955          58 :         if (wps_process_pubkey(wps, attr->public_key, attr->public_key_len) ||
     956          58 :             wps_process_authenticator(wps, attr->authenticator, msg) ||
     957          29 :             wps_process_device_attrs(&wps->peer_dev, attr)) {
     958           0 :                 wps->state = SEND_WSC_NACK;
     959           0 :                 return WPS_CONTINUE;
     960             :         }
     961             : 
     962             : #ifdef CONFIG_WPS_NFC
     963          29 :         if (wps->peer_pubkey_hash_set) {
     964             :                 struct wpabuf *decrypted;
     965             :                 struct wps_parse_attr eattr;
     966             : 
     967           0 :                 decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings,
     968             :                                                       attr->encr_settings_len);
     969           0 :                 if (decrypted == NULL) {
     970           0 :                         wpa_printf(MSG_DEBUG, "WPS: Failed to decrypt "
     971             :                                    "Encrypted Settings attribute");
     972           0 :                         wps->state = SEND_WSC_NACK;
     973           0 :                         return WPS_CONTINUE;
     974             :                 }
     975             : 
     976           0 :                 wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted "
     977             :                            "Settings attribute");
     978           0 :                 if (wps_parse_msg(decrypted, &eattr) < 0 ||
     979           0 :                     wps_process_key_wrap_auth(wps, decrypted,
     980           0 :                                               eattr.key_wrap_auth) ||
     981           0 :                     wps_process_creds(wps, eattr.cred, eattr.cred_len,
     982           0 :                                       eattr.num_cred, attr->version2 != NULL)) {
     983           0 :                         wpabuf_free(decrypted);
     984           0 :                         wps->state = SEND_WSC_NACK;
     985           0 :                         return WPS_CONTINUE;
     986             :                 }
     987           0 :                 wpabuf_free(decrypted);
     988             : 
     989           0 :                 wps->state = WPS_MSG_DONE;
     990           0 :                 return WPS_CONTINUE;
     991             :         }
     992             : #endif /* CONFIG_WPS_NFC */
     993             : 
     994          29 :         wps->state = SEND_M3;
     995          29 :         return WPS_CONTINUE;
     996             : }
     997             : 
     998             : 
     999           0 : static enum wps_process_res wps_process_m2d(struct wps_data *wps,
    1000             :                                             struct wps_parse_attr *attr)
    1001             : {
    1002           0 :         wpa_printf(MSG_DEBUG, "WPS: Received M2D");
    1003             : 
    1004           0 :         if (wps->state != RECV_M2) {
    1005           0 :                 wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
    1006           0 :                            "receiving M2D", wps->state);
    1007           0 :                 wps->state = SEND_WSC_NACK;
    1008           0 :                 return WPS_CONTINUE;
    1009             :         }
    1010             : 
    1011           0 :         wpa_hexdump_ascii(MSG_DEBUG, "WPS: Manufacturer",
    1012           0 :                           attr->manufacturer, attr->manufacturer_len);
    1013           0 :         wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Name",
    1014           0 :                           attr->model_name, attr->model_name_len);
    1015           0 :         wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Number",
    1016           0 :                           attr->model_number, attr->model_number_len);
    1017           0 :         wpa_hexdump_ascii(MSG_DEBUG, "WPS: Serial Number",
    1018           0 :                           attr->serial_number, attr->serial_number_len);
    1019           0 :         wpa_hexdump_ascii(MSG_DEBUG, "WPS: Device Name",
    1020           0 :                           attr->dev_name, attr->dev_name_len);
    1021             : 
    1022           0 :         if (wps->wps->event_cb) {
    1023             :                 union wps_event_data data;
    1024           0 :                 struct wps_event_m2d *m2d = &data.m2d;
    1025           0 :                 os_memset(&data, 0, sizeof(data));
    1026           0 :                 if (attr->config_methods)
    1027           0 :                         m2d->config_methods =
    1028           0 :                                 WPA_GET_BE16(attr->config_methods);
    1029           0 :                 m2d->manufacturer = attr->manufacturer;
    1030           0 :                 m2d->manufacturer_len = attr->manufacturer_len;
    1031           0 :                 m2d->model_name = attr->model_name;
    1032           0 :                 m2d->model_name_len = attr->model_name_len;
    1033           0 :                 m2d->model_number = attr->model_number;
    1034           0 :                 m2d->model_number_len = attr->model_number_len;
    1035           0 :                 m2d->serial_number = attr->serial_number;
    1036           0 :                 m2d->serial_number_len = attr->serial_number_len;
    1037           0 :                 m2d->dev_name = attr->dev_name;
    1038           0 :                 m2d->dev_name_len = attr->dev_name_len;
    1039           0 :                 m2d->primary_dev_type = attr->primary_dev_type;
    1040           0 :                 if (attr->config_error)
    1041           0 :                         m2d->config_error =
    1042           0 :                                 WPA_GET_BE16(attr->config_error);
    1043           0 :                 if (attr->dev_password_id)
    1044           0 :                         m2d->dev_password_id =
    1045           0 :                                 WPA_GET_BE16(attr->dev_password_id);
    1046           0 :                 wps->wps->event_cb(wps->wps->cb_ctx, WPS_EV_M2D, &data);
    1047             :         }
    1048             : 
    1049           0 :         wps->state = RECEIVED_M2D;
    1050           0 :         return WPS_CONTINUE;
    1051             : }
    1052             : 
    1053             : 
    1054          29 : static enum wps_process_res wps_process_m4(struct wps_data *wps,
    1055             :                                            const struct wpabuf *msg,
    1056             :                                            struct wps_parse_attr *attr)
    1057             : {
    1058             :         struct wpabuf *decrypted;
    1059             :         struct wps_parse_attr eattr;
    1060             : 
    1061          29 :         wpa_printf(MSG_DEBUG, "WPS: Received M4");
    1062             : 
    1063          29 :         if (wps->state != RECV_M4) {
    1064           0 :                 wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
    1065           0 :                            "receiving M4", wps->state);
    1066           0 :                 wps->state = SEND_WSC_NACK;
    1067           0 :                 return WPS_CONTINUE;
    1068             :         }
    1069             : 
    1070          58 :         if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) ||
    1071          58 :             wps_process_authenticator(wps, attr->authenticator, msg) ||
    1072          58 :             wps_process_r_hash1(wps, attr->r_hash1) ||
    1073          29 :             wps_process_r_hash2(wps, attr->r_hash2)) {
    1074           0 :                 wps->state = SEND_WSC_NACK;
    1075           0 :                 return WPS_CONTINUE;
    1076             :         }
    1077             : 
    1078          29 :         decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings,
    1079             :                                               attr->encr_settings_len);
    1080          29 :         if (decrypted == NULL) {
    1081           0 :                 wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted "
    1082             :                            "Settings attribute");
    1083           0 :                 wps->state = SEND_WSC_NACK;
    1084           0 :                 return WPS_CONTINUE;
    1085             :         }
    1086             : 
    1087          29 :         if (wps_validate_m4_encr(decrypted, attr->version2 != NULL) < 0) {
    1088           0 :                 wpabuf_free(decrypted);
    1089           0 :                 wps->state = SEND_WSC_NACK;
    1090           0 :                 return WPS_CONTINUE;
    1091             :         }
    1092             : 
    1093          29 :         wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings "
    1094             :                    "attribute");
    1095          58 :         if (wps_parse_msg(decrypted, &eattr) < 0 ||
    1096          58 :             wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
    1097          29 :             wps_process_r_snonce1(wps, eattr.r_snonce1)) {
    1098           4 :                 wpabuf_free(decrypted);
    1099           4 :                 wps->state = SEND_WSC_NACK;
    1100           4 :                 return WPS_CONTINUE;
    1101             :         }
    1102          25 :         wpabuf_free(decrypted);
    1103             : 
    1104          25 :         wps->state = SEND_M5;
    1105          25 :         return WPS_CONTINUE;
    1106             : }
    1107             : 
    1108             : 
    1109          25 : static enum wps_process_res wps_process_m6(struct wps_data *wps,
    1110             :                                            const struct wpabuf *msg,
    1111             :                                            struct wps_parse_attr *attr)
    1112             : {
    1113             :         struct wpabuf *decrypted;
    1114             :         struct wps_parse_attr eattr;
    1115             : 
    1116          25 :         wpa_printf(MSG_DEBUG, "WPS: Received M6");
    1117             : 
    1118          25 :         if (wps->state != RECV_M6) {
    1119           0 :                 wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
    1120           0 :                            "receiving M6", wps->state);
    1121           0 :                 wps->state = SEND_WSC_NACK;
    1122           0 :                 return WPS_CONTINUE;
    1123             :         }
    1124             : 
    1125          50 :         if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) ||
    1126          25 :             wps_process_authenticator(wps, attr->authenticator, msg)) {
    1127           0 :                 wps->state = SEND_WSC_NACK;
    1128           0 :                 return WPS_CONTINUE;
    1129             :         }
    1130             : 
    1131          25 :         decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings,
    1132             :                                               attr->encr_settings_len);
    1133          25 :         if (decrypted == NULL) {
    1134           0 :                 wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted "
    1135             :                            "Settings attribute");
    1136           0 :                 wps->state = SEND_WSC_NACK;
    1137           0 :                 return WPS_CONTINUE;
    1138             :         }
    1139             : 
    1140          25 :         if (wps_validate_m6_encr(decrypted, attr->version2 != NULL) < 0) {
    1141           0 :                 wpabuf_free(decrypted);
    1142           0 :                 wps->state = SEND_WSC_NACK;
    1143           0 :                 return WPS_CONTINUE;
    1144             :         }
    1145             : 
    1146          25 :         wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings "
    1147             :                    "attribute");
    1148          50 :         if (wps_parse_msg(decrypted, &eattr) < 0 ||
    1149          50 :             wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
    1150          25 :             wps_process_r_snonce2(wps, eattr.r_snonce2)) {
    1151           2 :                 wpabuf_free(decrypted);
    1152           2 :                 wps->state = SEND_WSC_NACK;
    1153           2 :                 return WPS_CONTINUE;
    1154             :         }
    1155          23 :         wpabuf_free(decrypted);
    1156             : 
    1157          23 :         if (wps->wps->ap)
    1158          23 :                 wps->wps->event_cb(wps->wps->cb_ctx, WPS_EV_AP_PIN_SUCCESS,
    1159             :                                    NULL);
    1160             : 
    1161          23 :         wps->state = SEND_M7;
    1162          23 :         return WPS_CONTINUE;
    1163             : }
    1164             : 
    1165             : 
    1166           8 : static enum wps_process_res wps_process_m8(struct wps_data *wps,
    1167             :                                            const struct wpabuf *msg,
    1168             :                                            struct wps_parse_attr *attr)
    1169             : {
    1170             :         struct wpabuf *decrypted;
    1171             :         struct wps_parse_attr eattr;
    1172             : 
    1173           8 :         wpa_printf(MSG_DEBUG, "WPS: Received M8");
    1174             : 
    1175           8 :         if (wps->state != RECV_M8) {
    1176           0 :                 wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
    1177           0 :                            "receiving M8", wps->state);
    1178           0 :                 wps->state = SEND_WSC_NACK;
    1179           0 :                 return WPS_CONTINUE;
    1180             :         }
    1181             : 
    1182          16 :         if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) ||
    1183           8 :             wps_process_authenticator(wps, attr->authenticator, msg)) {
    1184           0 :                 wps->state = SEND_WSC_NACK;
    1185           0 :                 return WPS_CONTINUE;
    1186             :         }
    1187             : 
    1188           8 :         if (wps->wps->ap && wps->wps->ap_setup_locked) {
    1189             :                 /*
    1190             :                  * Stop here if special ap_setup_locked == 2 mode allowed the
    1191             :                  * protocol to continue beyond M2. This allows ER to learn the
    1192             :                  * current AP settings without changing them.
    1193             :                  */
    1194           0 :                 wpa_printf(MSG_DEBUG, "WPS: AP Setup is locked - refuse "
    1195             :                            "registration of a new Registrar");
    1196           0 :                 wps->config_error = WPS_CFG_SETUP_LOCKED;
    1197           0 :                 wps->state = SEND_WSC_NACK;
    1198           0 :                 return WPS_CONTINUE;
    1199             :         }
    1200             : 
    1201           8 :         decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings,
    1202             :                                               attr->encr_settings_len);
    1203           8 :         if (decrypted == NULL) {
    1204           0 :                 wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted "
    1205             :                            "Settings attribute");
    1206           0 :                 wps->state = SEND_WSC_NACK;
    1207           0 :                 return WPS_CONTINUE;
    1208             :         }
    1209             : 
    1210           8 :         if (wps_validate_m8_encr(decrypted, wps->wps->ap,
    1211           8 :                                  attr->version2 != NULL) < 0) {
    1212           0 :                 wpabuf_free(decrypted);
    1213           0 :                 wps->state = SEND_WSC_NACK;
    1214           0 :                 return WPS_CONTINUE;
    1215             :         }
    1216             : 
    1217           8 :         wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings "
    1218             :                    "attribute");
    1219          16 :         if (wps_parse_msg(decrypted, &eattr) < 0 ||
    1220          16 :             wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
    1221           8 :             wps_process_creds(wps, eattr.cred, eattr.cred_len,
    1222          16 :                               eattr.num_cred, attr->version2 != NULL) ||
    1223           8 :             wps_process_ap_settings_e(wps, &eattr, decrypted,
    1224           8 :                                       attr->version2 != NULL)) {
    1225           1 :                 wpabuf_free(decrypted);
    1226           1 :                 wps->state = SEND_WSC_NACK;
    1227           1 :                 return WPS_CONTINUE;
    1228             :         }
    1229           7 :         wpabuf_free(decrypted);
    1230             : 
    1231           7 :         wps->state = WPS_MSG_DONE;
    1232           7 :         return WPS_CONTINUE;
    1233             : }
    1234             : 
    1235             : 
    1236          97 : static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps,
    1237             :                                                 const struct wpabuf *msg)
    1238             : {
    1239             :         struct wps_parse_attr attr;
    1240          97 :         enum wps_process_res ret = WPS_CONTINUE;
    1241             : 
    1242          97 :         wpa_printf(MSG_DEBUG, "WPS: Received WSC_MSG");
    1243             : 
    1244          97 :         if (wps_parse_msg(msg, &attr) < 0)
    1245           0 :                 return WPS_FAILURE;
    1246             : 
    1247         194 :         if (attr.enrollee_nonce == NULL ||
    1248          97 :             os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN) != 0) {
    1249           0 :                 wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce");
    1250           0 :                 return WPS_FAILURE;
    1251             :         }
    1252             : 
    1253          97 :         if (attr.msg_type == NULL) {
    1254           0 :                 wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
    1255           0 :                 wps->state = SEND_WSC_NACK;
    1256           0 :                 return WPS_CONTINUE;
    1257             :         }
    1258             : 
    1259          97 :         switch (*attr.msg_type) {
    1260             :         case WPS_M2:
    1261          35 :                 if (wps_validate_m2(msg) < 0)
    1262           0 :                         return WPS_FAILURE;
    1263          35 :                 ret = wps_process_m2(wps, msg, &attr);
    1264          35 :                 break;
    1265             :         case WPS_M2D:
    1266           0 :                 if (wps_validate_m2d(msg) < 0)
    1267           0 :                         return WPS_FAILURE;
    1268           0 :                 ret = wps_process_m2d(wps, &attr);
    1269           0 :                 break;
    1270             :         case WPS_M4:
    1271          29 :                 if (wps_validate_m4(msg) < 0)
    1272           0 :                         return WPS_FAILURE;
    1273          29 :                 ret = wps_process_m4(wps, msg, &attr);
    1274          29 :                 if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
    1275           4 :                         wps_fail_event(wps->wps, WPS_M4, wps->config_error,
    1276           4 :                                        wps->error_indication,
    1277           4 :                                        wps->peer_dev.mac_addr);
    1278          29 :                 break;
    1279             :         case WPS_M6:
    1280          25 :                 if (wps_validate_m6(msg) < 0)
    1281           0 :                         return WPS_FAILURE;
    1282          25 :                 ret = wps_process_m6(wps, msg, &attr);
    1283          25 :                 if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
    1284           2 :                         wps_fail_event(wps->wps, WPS_M6, wps->config_error,
    1285           2 :                                        wps->error_indication,
    1286           2 :                                        wps->peer_dev.mac_addr);
    1287          25 :                 break;
    1288             :         case WPS_M8:
    1289           8 :                 if (wps_validate_m8(msg) < 0)
    1290           0 :                         return WPS_FAILURE;
    1291           8 :                 ret = wps_process_m8(wps, msg, &attr);
    1292           8 :                 if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
    1293           1 :                         wps_fail_event(wps->wps, WPS_M8, wps->config_error,
    1294           1 :                                        wps->error_indication,
    1295           1 :                                        wps->peer_dev.mac_addr);
    1296           8 :                 break;
    1297             :         default:
    1298           0 :                 wpa_printf(MSG_DEBUG, "WPS: Unsupported Message Type %d",
    1299           0 :                            *attr.msg_type);
    1300           0 :                 return WPS_FAILURE;
    1301             :         }
    1302             : 
    1303             :         /*
    1304             :          * Save a copy of the last message for Authenticator derivation if we
    1305             :          * are continuing. However, skip M2D since it is not authenticated and
    1306             :          * neither is the ACK/NACK response frame. This allows the possibly
    1307             :          * following M2 to be processed correctly by using the previously sent
    1308             :          * M1 in Authenticator derivation.
    1309             :          */
    1310          97 :         if (ret == WPS_CONTINUE && *attr.msg_type != WPS_M2D) {
    1311             :                 /* Save a copy of the last message for Authenticator derivation
    1312             :                  */
    1313          97 :                 wpabuf_free(wps->last_msg);
    1314          97 :                 wps->last_msg = wpabuf_dup(msg);
    1315             :         }
    1316             : 
    1317          97 :         return ret;
    1318             : }
    1319             : 
    1320             : 
    1321           6 : static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps,
    1322             :                                                 const struct wpabuf *msg)
    1323             : {
    1324             :         struct wps_parse_attr attr;
    1325             : 
    1326           6 :         wpa_printf(MSG_DEBUG, "WPS: Received WSC_ACK");
    1327             : 
    1328           6 :         if (wps_parse_msg(msg, &attr) < 0)
    1329           0 :                 return WPS_FAILURE;
    1330             : 
    1331           6 :         if (attr.msg_type == NULL) {
    1332           0 :                 wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
    1333           0 :                 return WPS_FAILURE;
    1334             :         }
    1335             : 
    1336           6 :         if (*attr.msg_type != WPS_WSC_ACK) {
    1337           0 :                 wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d",
    1338           0 :                            *attr.msg_type);
    1339           0 :                 return WPS_FAILURE;
    1340             :         }
    1341             : 
    1342          12 :         if (attr.registrar_nonce == NULL ||
    1343           6 :             os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN) != 0)
    1344             :         {
    1345           0 :                 wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce");
    1346           0 :                 return WPS_FAILURE;
    1347             :         }
    1348             : 
    1349          12 :         if (attr.enrollee_nonce == NULL ||
    1350           6 :             os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN) != 0) {
    1351           0 :                 wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce");
    1352           0 :                 return WPS_FAILURE;
    1353             :         }
    1354             : 
    1355           6 :         if (wps->state == RECV_ACK && wps->wps->ap) {
    1356           6 :                 wpa_printf(MSG_DEBUG, "WPS: External Registrar registration "
    1357             :                            "completed successfully");
    1358           6 :                 wps_success_event(wps->wps, wps->peer_dev.mac_addr);
    1359           6 :                 wps->state = WPS_FINISHED;
    1360           6 :                 return WPS_DONE;
    1361             :         }
    1362             : 
    1363           0 :         return WPS_FAILURE;
    1364             : }
    1365             : 
    1366             : 
    1367          28 : static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps,
    1368             :                                                  const struct wpabuf *msg)
    1369             : {
    1370             :         struct wps_parse_attr attr;
    1371             :         u16 config_error;
    1372             : 
    1373          28 :         wpa_printf(MSG_DEBUG, "WPS: Received WSC_NACK");
    1374             : 
    1375          28 :         if (wps_parse_msg(msg, &attr) < 0)
    1376           0 :                 return WPS_FAILURE;
    1377             : 
    1378          28 :         if (attr.msg_type == NULL) {
    1379           0 :                 wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
    1380           0 :                 return WPS_FAILURE;
    1381             :         }
    1382             : 
    1383          28 :         if (*attr.msg_type != WPS_WSC_NACK) {
    1384           0 :                 wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d",
    1385           0 :                            *attr.msg_type);
    1386           0 :                 return WPS_FAILURE;
    1387             :         }
    1388             : 
    1389          56 :         if (attr.registrar_nonce == NULL ||
    1390          28 :             os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN) != 0)
    1391             :         {
    1392           0 :                 wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce");
    1393           0 :                 wpa_hexdump(MSG_DEBUG, "WPS: Received Registrar Nonce",
    1394           0 :                             attr.registrar_nonce, WPS_NONCE_LEN);
    1395           0 :                 wpa_hexdump(MSG_DEBUG, "WPS: Expected Registrar Nonce",
    1396           0 :                             wps->nonce_r, WPS_NONCE_LEN);
    1397           0 :                 return WPS_FAILURE;
    1398             :         }
    1399             : 
    1400          56 :         if (attr.enrollee_nonce == NULL ||
    1401          28 :             os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN) != 0) {
    1402           0 :                 wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce");
    1403           0 :                 wpa_hexdump(MSG_DEBUG, "WPS: Received Enrollee Nonce",
    1404           0 :                             attr.enrollee_nonce, WPS_NONCE_LEN);
    1405           0 :                 wpa_hexdump(MSG_DEBUG, "WPS: Expected Enrollee Nonce",
    1406           0 :                             wps->nonce_e, WPS_NONCE_LEN);
    1407           0 :                 return WPS_FAILURE;
    1408             :         }
    1409             : 
    1410          28 :         if (attr.config_error == NULL) {
    1411           0 :                 wpa_printf(MSG_DEBUG, "WPS: No Configuration Error attribute "
    1412             :                            "in WSC_NACK");
    1413           0 :                 return WPS_FAILURE;
    1414             :         }
    1415             : 
    1416          28 :         config_error = WPA_GET_BE16(attr.config_error);
    1417          28 :         wpa_printf(MSG_DEBUG, "WPS: Registrar terminated negotiation with "
    1418             :                    "Configuration Error %d", config_error);
    1419             : 
    1420          28 :         switch (wps->state) {
    1421             :         case RECV_M4:
    1422           0 :                 wps_fail_event(wps->wps, WPS_M3, config_error,
    1423           0 :                                wps->error_indication, wps->peer_dev.mac_addr);
    1424           0 :                 break;
    1425             :         case RECV_M6:
    1426           0 :                 wps_fail_event(wps->wps, WPS_M5, config_error,
    1427           0 :                                wps->error_indication, wps->peer_dev.mac_addr);
    1428           0 :                 break;
    1429             :         case RECV_M8:
    1430          15 :                 wps_fail_event(wps->wps, WPS_M7, config_error,
    1431          15 :                                wps->error_indication, wps->peer_dev.mac_addr);
    1432          15 :                 break;
    1433             :         default:
    1434          13 :                 break;
    1435             :         }
    1436             : 
    1437             :         /* Followed by NACK if Enrollee is Supplicant or EAP-Failure if
    1438             :          * Enrollee is Authenticator */
    1439          28 :         wps->state = SEND_WSC_NACK;
    1440             : 
    1441          28 :         return WPS_FAILURE;
    1442             : }
    1443             : 
    1444             : 
    1445         131 : enum wps_process_res wps_enrollee_process_msg(struct wps_data *wps,
    1446             :                                               enum wsc_op_code op_code,
    1447             :                                               const struct wpabuf *msg)
    1448             : {
    1449             : 
    1450         131 :         wpa_printf(MSG_DEBUG, "WPS: Processing received message (len=%lu "
    1451             :                    "op_code=%d)",
    1452             :                    (unsigned long) wpabuf_len(msg), op_code);
    1453             : 
    1454         131 :         if (op_code == WSC_UPnP) {
    1455             :                 /* Determine the OpCode based on message type attribute */
    1456             :                 struct wps_parse_attr attr;
    1457           8 :                 if (wps_parse_msg(msg, &attr) == 0 && attr.msg_type) {
    1458           8 :                         if (*attr.msg_type == WPS_WSC_ACK)
    1459           0 :                                 op_code = WSC_ACK;
    1460           8 :                         else if (*attr.msg_type == WPS_WSC_NACK)
    1461           1 :                                 op_code = WSC_NACK;
    1462             :                 }
    1463             :         }
    1464             : 
    1465         131 :         switch (op_code) {
    1466             :         case WSC_MSG:
    1467             :         case WSC_UPnP:
    1468          97 :                 return wps_process_wsc_msg(wps, msg);
    1469             :         case WSC_ACK:
    1470           6 :                 if (wps_validate_wsc_ack(msg) < 0)
    1471           0 :                         return WPS_FAILURE;
    1472           6 :                 return wps_process_wsc_ack(wps, msg);
    1473             :         case WSC_NACK:
    1474          28 :                 if (wps_validate_wsc_nack(msg) < 0)
    1475           0 :                         return WPS_FAILURE;
    1476          28 :                 return wps_process_wsc_nack(wps, msg);
    1477             :         default:
    1478           0 :                 wpa_printf(MSG_DEBUG, "WPS: Unsupported op_code %d", op_code);
    1479           0 :                 return WPS_FAILURE;
    1480             :         }
    1481             : }

Generated by: LCOV version 1.10