LCOV - code coverage report
Current view: top level - src/wps - wps_enrollee.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1443382998 Lines: 790 834 94.7 %
Date: 2015-09-27 Functions: 37 37 100.0 %

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

Generated by: LCOV version 1.10