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