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

Generated by: LCOV version 1.10