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