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 : }
|