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

Generated by: LCOV version 1.10