]> git.ipfire.org Git - thirdparty/hostap.git/blame - src/wps/wps_registrar.c
WPS: Added option to disable AP auto-config on first registration
[thirdparty/hostap.git] / src / wps / wps_registrar.c
CommitLineData
ad08c363
JM
1/*
2 * Wi-Fi Protected Setup - Registrar
3 * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
11 *
12 * See README and COPYING for more details.
13 */
14
15#include "includes.h"
16
17#include "common.h"
18#include "sha256.h"
19#include "base64.h"
20#include "ieee802_11_defs.h"
21#include "eloop.h"
22#include "wps_i.h"
23#include "wps_dev_attr.h"
24
25
26struct wps_uuid_pin {
27 struct wps_uuid_pin *next;
28 u8 uuid[WPS_UUID_LEN];
08bec361 29 int wildcard_uuid;
ad08c363
JM
30 u8 *pin;
31 size_t pin_len;
32 int locked;
33};
34
35
36static void wps_free_pin(struct wps_uuid_pin *pin)
37{
38 os_free(pin->pin);
39 os_free(pin);
40}
41
42
43static void wps_free_pins(struct wps_uuid_pin *pins)
44{
45 struct wps_uuid_pin *pin, *prev;
46
47 pin = pins;
48 while (pin) {
49 prev = pin;
50 pin = pin->next;
51 wps_free_pin(prev);
52 }
53}
54
55
56struct wps_pbc_session {
57 struct wps_pbc_session *next;
58 u8 addr[ETH_ALEN];
59 u8 uuid_e[WPS_UUID_LEN];
60 struct os_time timestamp;
61};
62
63
64static void wps_free_pbc_sessions(struct wps_pbc_session *pbc)
65{
66 struct wps_pbc_session *prev;
67
68 while (pbc) {
69 prev = pbc;
70 pbc = pbc->next;
71 os_free(prev);
72 }
73}
74
75
76struct wps_registrar {
77 struct wps_context *wps;
78
79 int pbc;
80 int selected_registrar;
81
82 int (*new_psk_cb)(void *ctx, const u8 *mac_addr, const u8 *psk,
83 size_t psk_len);
84 int (*set_ie_cb)(void *ctx, const u8 *beacon_ie, size_t beacon_ie_len,
85 const u8 *probe_resp_ie, size_t probe_resp_ie_len);
86 void (*pin_needed_cb)(void *ctx, const u8 *uuid_e,
87 const struct wps_device_data *dev);
aabe26a1
JM
88 void (*reg_success_cb)(void *ctx, const u8 *mac_addr,
89 const u8 *uuid_e);
ad08c363
JM
90 void *cb_ctx;
91
92 struct wps_uuid_pin *pins;
93 struct wps_pbc_session *pbc_sessions;
6fa68a0e
JM
94
95 int skip_cred_build;
96 struct wpabuf *extra_cred;
aabe26a1 97 int disable_auto_conf;
ad08c363
JM
98};
99
100
101static int wps_set_ie(struct wps_registrar *reg);
102static void wps_registrar_pbc_timeout(void *eloop_ctx, void *timeout_ctx);
103
104
105static void wps_registrar_add_pbc_session(struct wps_registrar *reg,
106 const u8 *addr, const u8 *uuid_e)
107{
108 struct wps_pbc_session *pbc, *prev = NULL;
109 struct os_time now;
110
111 os_get_time(&now);
112
113 pbc = reg->pbc_sessions;
114 while (pbc) {
115 if (os_memcmp(pbc->addr, addr, ETH_ALEN) == 0 &&
116 os_memcmp(pbc->uuid_e, uuid_e, WPS_UUID_LEN) == 0) {
117 if (prev)
118 prev->next = pbc->next;
119 else
120 reg->pbc_sessions = pbc->next;
121 break;
122 }
123 prev = pbc;
124 pbc = pbc->next;
125 }
126
127 if (!pbc) {
128 pbc = os_zalloc(sizeof(*pbc));
129 if (pbc == NULL)
130 return;
131 os_memcpy(pbc->addr, addr, ETH_ALEN);
132 if (uuid_e)
133 os_memcpy(pbc->uuid_e, uuid_e, WPS_UUID_LEN);
134 }
135
136 pbc->next = reg->pbc_sessions;
137 reg->pbc_sessions = pbc;
138 pbc->timestamp = now;
139
140 /* remove entries that have timed out */
141 prev = pbc;
142 pbc = pbc->next;
143
144 while (pbc) {
145 if (now.sec > pbc->timestamp.sec + WPS_PBC_WALK_TIME) {
146 prev->next = NULL;
147 wps_free_pbc_sessions(pbc);
148 break;
149 }
150 prev = pbc;
151 pbc = pbc->next;
152 }
153}
154
155
156static void wps_registrar_remove_pbc_session(struct wps_registrar *reg,
157 const u8 *addr, const u8 *uuid_e)
158{
159 struct wps_pbc_session *pbc, *prev = NULL;
160
161 pbc = reg->pbc_sessions;
162 while (pbc) {
163 if (os_memcmp(pbc->addr, addr, ETH_ALEN) == 0 &&
164 os_memcmp(pbc->uuid_e, uuid_e, WPS_UUID_LEN) == 0) {
165 if (prev)
166 prev->next = pbc->next;
167 else
168 reg->pbc_sessions = pbc->next;
169 os_free(pbc);
170 break;
171 }
172 prev = pbc;
173 pbc = pbc->next;
174 }
175}
176
177
7e5ba1b9
JM
178static int wps_registrar_pbc_overlap(struct wps_registrar *reg,
179 const u8 *addr, const u8 *uuid_e)
ad08c363
JM
180{
181 int count = 0;
182 struct wps_pbc_session *pbc;
183 struct os_time now;
184
185 os_get_time(&now);
186
187 for (pbc = reg->pbc_sessions; pbc; pbc = pbc->next) {
188 if (now.sec > pbc->timestamp.sec + WPS_PBC_WALK_TIME)
189 break;
190 if (addr == NULL || os_memcmp(addr, pbc->addr, ETH_ALEN) ||
191 uuid_e == NULL ||
192 os_memcmp(uuid_e, pbc->uuid_e, WPS_UUID_LEN))
193 count++;
194 }
195
196 if (addr || uuid_e)
197 count++;
198
199 return count > 1 ? 1 : 0;
200}
201
202
203static int wps_build_wps_state(struct wps_context *wps, struct wpabuf *msg)
204{
205 wpa_printf(MSG_DEBUG, "WPS: * Wi-Fi Protected Setup State (%d)",
206 wps->wps_state);
207 wpabuf_put_be16(msg, ATTR_WPS_STATE);
208 wpabuf_put_be16(msg, 1);
209 wpabuf_put_u8(msg, wps->wps_state);
210 return 0;
211}
212
213
214static int wps_build_ap_setup_locked(struct wps_context *wps,
215 struct wpabuf *msg)
216{
217 if (wps->ap_setup_locked) {
218 wpa_printf(MSG_DEBUG, "WPS: * AP Setup Locked");
219 wpabuf_put_be16(msg, ATTR_AP_SETUP_LOCKED);
220 wpabuf_put_be16(msg, 1);
221 wpabuf_put_u8(msg, 1);
222 }
223 return 0;
224}
225
226
227static int wps_build_selected_registrar(struct wps_registrar *reg,
228 struct wpabuf *msg)
229{
230 if (!reg->selected_registrar)
231 return 0;
232 wpa_printf(MSG_DEBUG, "WPS: * Selected Registrar");
233 wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR);
234 wpabuf_put_be16(msg, 1);
235 wpabuf_put_u8(msg, 1);
236 return 0;
237}
238
239
240static int wps_build_sel_reg_dev_password_id(struct wps_registrar *reg,
241 struct wpabuf *msg)
242{
243 u16 id = reg->pbc ? DEV_PW_PUSHBUTTON : DEV_PW_DEFAULT;
244 if (!reg->selected_registrar)
245 return 0;
246 wpa_printf(MSG_DEBUG, "WPS: * Device Password ID (%d)", id);
247 wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID);
248 wpabuf_put_be16(msg, 2);
249 wpabuf_put_be16(msg, id);
250 return 0;
251}
252
253
254static int wps_build_sel_reg_config_methods(struct wps_registrar *reg,
255 struct wpabuf *msg)
256{
257 u16 methods;
258 if (!reg->selected_registrar)
259 return 0;
260 methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON;
261 if (reg->pbc)
262 methods |= WPS_CONFIG_PUSHBUTTON;
263 wpa_printf(MSG_DEBUG, "WPS: * Selected Registrar Config Methods (%x)",
264 methods);
265 wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR_CONFIG_METHODS);
266 wpabuf_put_be16(msg, 2);
267 wpabuf_put_be16(msg, methods);
268 return 0;
269}
270
271
272static int wps_build_probe_config_methods(struct wps_registrar *reg,
273 struct wpabuf *msg)
274{
275 u16 methods;
276 methods = 0;
277 wpa_printf(MSG_DEBUG, "WPS: * Config Methods (%x)", methods);
278 wpabuf_put_be16(msg, ATTR_CONFIG_METHODS);
279 wpabuf_put_be16(msg, 2);
280 wpabuf_put_be16(msg, methods);
281 return 0;
282}
283
284
c0d041d9
JM
285static int wps_build_config_methods_r(struct wps_registrar *reg,
286 struct wpabuf *msg)
ad08c363
JM
287{
288 u16 methods;
289 methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON;
290 if (reg->pbc)
291 methods |= WPS_CONFIG_PUSHBUTTON;
c0d041d9 292 return wps_build_config_methods(msg, methods);
ad08c363
JM
293}
294
295
296static int wps_build_resp_type(struct wps_registrar *reg, struct wpabuf *msg)
297{
298 u8 resp = reg->wps->ap ? WPS_RESP_AP : WPS_RESP_REGISTRAR;
299 wpa_printf(MSG_DEBUG, "WPS: * Response Type (%d)", resp);
300 wpabuf_put_be16(msg, ATTR_RESPONSE_TYPE);
301 wpabuf_put_be16(msg, 1);
302 wpabuf_put_u8(msg, resp);
303 return 0;
304}
305
306
f90c86d4
JM
307/**
308 * wps_registrar_init - Initialize WPS Registrar data
309 * @wps: Pointer to longterm WPS context
310 * @cfg: Registrar configuration
311 * Returns: Pointer to allocated Registrar data or %NULL on failure
312 *
313 * This function is used to initialize WPS Registrar functionality. It can be
314 * used for a single Registrar run (e.g., when run in a supplicant) or multiple
315 * runs (e.g., when run as an internal Registrar in an AP). Caller is
316 * responsible for freeing the returned data with wps_registrar_deinit() when
317 * Registrar functionality is not needed anymore.
318 */
ad08c363
JM
319struct wps_registrar *
320wps_registrar_init(struct wps_context *wps,
321 const struct wps_registrar_config *cfg)
322{
323 struct wps_registrar *reg = os_zalloc(sizeof(*reg));
324 if (reg == NULL)
325 return NULL;
326
327 reg->wps = wps;
328 reg->new_psk_cb = cfg->new_psk_cb;
329 reg->set_ie_cb = cfg->set_ie_cb;
330 reg->pin_needed_cb = cfg->pin_needed_cb;
aabe26a1 331 reg->reg_success_cb = cfg->reg_success_cb;
ad08c363 332 reg->cb_ctx = cfg->cb_ctx;
6fa68a0e
JM
333 reg->skip_cred_build = cfg->skip_cred_build;
334 if (cfg->extra_cred) {
335 reg->extra_cred = wpabuf_alloc_copy(cfg->extra_cred,
336 cfg->extra_cred_len);
337 if (reg->extra_cred == NULL) {
338 os_free(reg);
339 return NULL;
340 }
341 }
aabe26a1 342 reg->disable_auto_conf = cfg->disable_auto_conf;
ad08c363
JM
343
344 if (wps_set_ie(reg)) {
345 wps_registrar_deinit(reg);
346 return NULL;
347 }
348
349 return reg;
350}
351
352
f90c86d4
JM
353/**
354 * wps_registrar_deinit - Deinitialize WPS Registrar data
08c0f067 355 * @reg: Registrar data from wps_registrar_init()
f90c86d4 356 */
ad08c363
JM
357void wps_registrar_deinit(struct wps_registrar *reg)
358{
359 if (reg == NULL)
360 return;
361 eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL);
362 wps_free_pins(reg->pins);
363 wps_free_pbc_sessions(reg->pbc_sessions);
6fa68a0e 364 wpabuf_free(reg->extra_cred);
ad08c363
JM
365 os_free(reg);
366}
367
368
08c0f067
JM
369/**
370 * wps_registrar_add_pin - Configure a new PIN for Registrar
371 * @reg: Registrar data from wps_registrar_init()
372 * @uuid: UUID-E or %NULL for wildcard (any UUID)
373 * @pin: PIN (Device Password)
374 * @pin_len: Length of pin in octets
375 * Returns: 0 on success, -1 on failure
376 */
ad08c363
JM
377int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *uuid,
378 const u8 *pin, size_t pin_len)
379{
380 struct wps_uuid_pin *p;
381
382 p = os_zalloc(sizeof(*p));
383 if (p == NULL)
384 return -1;
08bec361
JM
385 if (uuid == NULL)
386 p->wildcard_uuid = 1;
387 else
388 os_memcpy(p->uuid, uuid, WPS_UUID_LEN);
ad08c363
JM
389 p->pin = os_malloc(pin_len);
390 if (p->pin == NULL) {
391 os_free(p);
392 return -1;
393 }
394 os_memcpy(p->pin, pin, pin_len);
395 p->pin_len = pin_len;
396
397 p->next = reg->pins;
398 reg->pins = p;
399
400 wpa_printf(MSG_DEBUG, "WPS: A new PIN configured");
401 wpa_hexdump(MSG_DEBUG, "WPS: UUID", uuid, WPS_UUID_LEN);
402 wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: PIN", pin, pin_len);
403 reg->selected_registrar = 1;
404 reg->pbc = 0;
405 wps_set_ie(reg);
406
407 return 0;
408}
409
410
08c0f067
JM
411/**
412 * wps_registrar_invalidate_pin - Invalidate a PIN for a specific UUID-E
413 * @reg: Registrar data from wps_registrar_init()
414 * @uuid: UUID-E
415 * Returns: 0 on success, -1 on failure (e.g., PIN not found)
416 */
ad08c363
JM
417int wps_registrar_invalidate_pin(struct wps_registrar *reg, const u8 *uuid)
418{
419 struct wps_uuid_pin *pin, *prev;
420
421 prev = NULL;
422 pin = reg->pins;
423 while (pin) {
424 if (os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) {
425 if (prev == NULL)
426 reg->pins = pin->next;
427 else
428 prev->next = pin->next;
429 wpa_hexdump(MSG_DEBUG, "WPS: Invalidated PIN for UUID",
430 pin->uuid, WPS_UUID_LEN);
431 wps_free_pin(pin);
432 return 0;
433 }
434 prev = pin;
435 pin = pin->next;
436 }
437
438 return -1;
439}
440
441
442static const u8 * wps_registrar_get_pin(struct wps_registrar *reg,
443 const u8 *uuid, size_t *pin_len)
444{
445 struct wps_uuid_pin *pin;
446
447 pin = reg->pins;
448 while (pin) {
08bec361
JM
449 if (!pin->wildcard_uuid &&
450 os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0)
451 break;
452 pin = pin->next;
453 }
454
455 if (!pin) {
456 /* Check for wildcard UUIDs since none of the UUID-specific
457 * PINs matched */
458 pin = reg->pins;
459 while (pin) {
460 if (pin->wildcard_uuid == 1) {
461 wpa_printf(MSG_DEBUG, "WPS: Found a wildcard "
462 "PIN. Assigned it for this UUID-E");
463 pin->wildcard_uuid = 2;
464 os_memcpy(pin->uuid, uuid, WPS_UUID_LEN);
465 break;
ad08c363 466 }
08bec361 467 pin = pin->next;
ad08c363 468 }
ad08c363
JM
469 }
470
08bec361
JM
471 if (!pin)
472 return NULL;
473
474 /*
475 * Lock the PIN to avoid attacks based on concurrent re-use of the PIN
476 * that could otherwise avoid PIN invalidations.
477 */
478 if (pin->locked) {
479 wpa_printf(MSG_DEBUG, "WPS: Selected PIN locked - do not "
480 "allow concurrent re-use");
481 return NULL;
482 }
483 *pin_len = pin->pin_len;
484 pin->locked = 1;
485 return pin->pin;
ad08c363
JM
486}
487
488
08c0f067
JM
489/**
490 * wps_registrar_unlock_pin - Unlock a PIN for a specific UUID-E
491 * @reg: Registrar data from wps_registrar_init()
492 * @uuid: UUID-E
493 * Returns: 0 on success, -1 on failure
494 *
495 * PINs are locked to enforce only one concurrent use. This function unlocks a
496 * PIN to allow it to be used again. If the specified PIN was configured using
497 * a wildcard UUID, it will be removed instead of allowing multiple uses.
498 */
ad08c363
JM
499int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid)
500{
501 struct wps_uuid_pin *pin;
502
503 pin = reg->pins;
504 while (pin) {
505 if (os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) {
08bec361
JM
506 if (pin->wildcard_uuid == 2) {
507 wpa_printf(MSG_DEBUG, "WPS: Invalidating used "
508 "wildcard PIN");
509 return wps_registrar_invalidate_pin(reg, uuid);
510 }
ad08c363
JM
511 pin->locked = 0;
512 return 0;
513 }
514 pin = pin->next;
515 }
516
517 return -1;
518}
519
520
08c0f067
JM
521static void wps_registrar_stop_pbc(struct wps_registrar *reg)
522{
523 reg->selected_registrar = 0;
524 reg->pbc = 0;
525 wps_set_ie(reg);
526}
527
528
ad08c363
JM
529static void wps_registrar_pbc_timeout(void *eloop_ctx, void *timeout_ctx)
530{
531 struct wps_registrar *reg = eloop_ctx;
532
533 wpa_printf(MSG_DEBUG, "WPS: PBC timed out - disable PBC mode");
08c0f067 534 wps_registrar_stop_pbc(reg);
ad08c363
JM
535}
536
537
08c0f067
JM
538/**
539 * wps_registrar_button_pushed - Notify Registrar that AP button was pushed
540 * @reg: Registrar data from wps_registrar_init()
541 * Returns: 0 on success, -1 on failure
542 *
543 * This function is called on an AP when a push button is pushed to activate
544 * PBC mode. The PBC mode will be stopped after walk time (2 minutes) timeout
545 * or when a PBC registration is completed.
546 */
ad08c363
JM
547int wps_registrar_button_pushed(struct wps_registrar *reg)
548{
549 if (wps_registrar_pbc_overlap(reg, NULL, NULL)) {
550 wpa_printf(MSG_DEBUG, "WPS: PBC overlap - do not start PBC "
551 "mode");
552 return -1;
553 }
554 wpa_printf(MSG_DEBUG, "WPS: Button pushed - PBC mode started");
555 reg->selected_registrar = 1;
556 reg->pbc = 1;
557 wps_set_ie(reg);
558
559 eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL);
560 eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wps_registrar_pbc_timeout,
561 reg, NULL);
562 return 0;
563}
564
565
566static void wps_registrar_pbc_completed(struct wps_registrar *reg)
567{
568 wpa_printf(MSG_DEBUG, "WPS: PBC completed - stopping PBC mode");
569 eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL);
08c0f067 570 wps_registrar_stop_pbc(reg);
ad08c363
JM
571}
572
573
08c0f067
JM
574/**
575 * wps_registrar_probe_req_rx - Notify Registrar of Probe Request
576 * @reg: Registrar data from wps_registrar_init()
577 * @addr: MAC address of the Probe Request sender
578 * @wps_data: WPS IE contents
579 *
580 * This function is called on an AP when a Probe Request with WPS IE is
581 * received. This is used to track PBC mode use and to detect possible overlap
582 * situation with other WPS APs.
583 */
ad08c363
JM
584void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr,
585 const struct wpabuf *wps_data)
586{
587 struct wps_parse_attr attr;
588 u16 methods;
589
590 wpa_hexdump_buf(MSG_MSGDUMP,
591 "WPS: Probe Request with WPS data received",
592 wps_data);
593
594 if (wps_parse_msg(wps_data, &attr) < 0 ||
595 attr.version == NULL || *attr.version != WPS_VERSION) {
596 wpa_printf(MSG_DEBUG, "WPS: Unsupported ProbeReq WPS IE "
597 "version 0x%x", attr.version ? *attr.version : 0);
598 return;
599 }
600
601 if (attr.config_methods == NULL) {
602 wpa_printf(MSG_DEBUG, "WPS: No Config Methods attribute in "
603 "Probe Request");
604 return;
605 }
606
607 methods = WPA_GET_BE16(attr.config_methods);
608 if (!(methods & WPS_CONFIG_PUSHBUTTON))
609 return; /* Not PBC */
610
611 wpa_printf(MSG_DEBUG, "WPS: Probe Request for PBC received from "
612 MACSTR, MAC2STR(addr));
613
614 wps_registrar_add_pbc_session(reg, addr, attr.uuid_e);
615}
616
617
618static int wps_cb_new_psk(struct wps_registrar *reg, const u8 *mac_addr,
619 const u8 *psk, size_t psk_len)
620{
621 if (reg->new_psk_cb == NULL)
622 return 0;
623
624 return reg->new_psk_cb(reg->cb_ctx, mac_addr, psk, psk_len);
625}
626
627
628static void wps_cb_pin_needed(struct wps_registrar *reg, const u8 *uuid_e,
629 const struct wps_device_data *dev)
630{
631 if (reg->pin_needed_cb == NULL)
632 return;
633
634 reg->pin_needed_cb(reg->cb_ctx, uuid_e, dev);
635}
636
637
aabe26a1
JM
638static void wps_cb_reg_success(struct wps_registrar *reg, const u8 *mac_addr,
639 const u8 *uuid_e)
640{
641 if (reg->reg_success_cb == NULL)
642 return;
643
644 reg->reg_success_cb(reg->cb_ctx, mac_addr, uuid_e);
645}
646
647
ad08c363
JM
648static int wps_cb_set_ie(struct wps_registrar *reg,
649 const struct wpabuf *beacon_ie,
650 const struct wpabuf *probe_resp_ie)
651{
652 if (reg->set_ie_cb == NULL)
653 return 0;
654
655 return reg->set_ie_cb(reg->cb_ctx, wpabuf_head(beacon_ie),
656 wpabuf_len(beacon_ie),
657 wpabuf_head(probe_resp_ie),
658 wpabuf_len(probe_resp_ie));
659}
660
661
351f09a2
JM
662/* Encapsulate WPS IE data with one (or more, if needed) IE headers */
663static struct wpabuf * wps_ie_encapsulate(struct wpabuf *data)
664{
665 struct wpabuf *ie;
666 const u8 *pos, *end;
667
668 ie = wpabuf_alloc(wpabuf_len(data) + 100);
669 if (ie == NULL) {
670 wpabuf_free(data);
671 return NULL;
672 }
673
674 pos = wpabuf_head(data);
675 end = pos + wpabuf_len(data);
676
677 while (end > pos) {
678 size_t frag_len = end - pos;
679 if (frag_len > 251)
680 frag_len = 251;
681 wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC);
682 wpabuf_put_u8(ie, 4 + frag_len);
683 wpabuf_put_be32(ie, WPS_DEV_OUI_WFA);
684 wpabuf_put_data(ie, pos, frag_len);
685 pos += frag_len;
686 }
687
688 wpabuf_free(data);
689
690 return ie;
691}
692
693
ad08c363
JM
694static int wps_set_ie(struct wps_registrar *reg)
695{
696 struct wpabuf *beacon;
697 struct wpabuf *probe;
698 int ret;
ad08c363
JM
699
700 wpa_printf(MSG_DEBUG, "WPS: Build Beacon and Probe Response IEs");
701
702 beacon = wpabuf_alloc(300);
703 if (beacon == NULL)
704 return -1;
351f09a2 705 probe = wpabuf_alloc(400);
ad08c363
JM
706 if (probe == NULL) {
707 wpabuf_free(beacon);
708 return -1;
709 }
710
ad08c363
JM
711 if (wps_build_version(beacon) ||
712 wps_build_wps_state(reg->wps, beacon) ||
713 wps_build_ap_setup_locked(reg->wps, beacon) ||
714 wps_build_selected_registrar(reg, beacon) ||
715 wps_build_sel_reg_dev_password_id(reg, beacon) ||
716 wps_build_sel_reg_config_methods(reg, beacon) ||
717 wps_build_version(probe) ||
718 wps_build_wps_state(reg->wps, probe) ||
719 wps_build_ap_setup_locked(reg->wps, probe) ||
720 wps_build_selected_registrar(reg, probe) ||
721 wps_build_sel_reg_dev_password_id(reg, probe) ||
722 wps_build_sel_reg_config_methods(reg, probe) ||
723 wps_build_resp_type(reg, probe) ||
c0d041d9 724 wps_build_uuid_e(probe, reg->wps->uuid) ||
ad08c363
JM
725 wps_build_device_attrs(&reg->wps->dev, probe) ||
726 wps_build_probe_config_methods(reg, probe) ||
120bd30c 727 wps_build_rf_bands(&reg->wps->dev, probe)) {
ad08c363
JM
728 wpabuf_free(beacon);
729 wpabuf_free(probe);
730 return -1;
731 }
732
351f09a2
JM
733 beacon = wps_ie_encapsulate(beacon);
734 probe = wps_ie_encapsulate(probe);
735
736 if (!beacon || !probe) {
737 wpabuf_free(beacon);
738 wpabuf_free(probe);
739 return -1;
740 }
ad08c363
JM
741
742 ret = wps_cb_set_ie(reg, beacon, probe);
743 wpabuf_free(beacon);
744 wpabuf_free(probe);
745
746 return ret;
747}
748
749
750static int wps_get_dev_password(struct wps_data *wps)
751{
752 const u8 *pin;
9e72e1d3 753 size_t pin_len = 0;
ad08c363
JM
754
755 os_free(wps->dev_password);
756 wps->dev_password = NULL;
757
758 if (wps->pbc) {
759 wpa_printf(MSG_DEBUG, "WPS: Use default PIN for PBC");
760 pin = (const u8 *) "00000000";
761 pin_len = 8;
762 } else {
41c00105 763 pin = wps_registrar_get_pin(wps->wps->registrar, wps->uuid_e,
ad08c363
JM
764 &pin_len);
765 }
766 if (pin == NULL) {
767 wpa_printf(MSG_DEBUG, "WPS: No Device Password available for "
768 "the Enrollee");
41c00105
JM
769 wps_cb_pin_needed(wps->wps->registrar, wps->uuid_e,
770 &wps->peer_dev);
ad08c363
JM
771 return -1;
772 }
773
774 wps->dev_password = os_malloc(pin_len);
775 if (wps->dev_password == NULL)
776 return -1;
777 os_memcpy(wps->dev_password, pin, pin_len);
778 wps->dev_password_len = pin_len;
779
780 return 0;
781}
782
783
784static int wps_build_uuid_r(struct wps_data *wps, struct wpabuf *msg)
785{
786 wpa_printf(MSG_DEBUG, "WPS: * UUID-R");
787 wpabuf_put_be16(msg, ATTR_UUID_R);
788 wpabuf_put_be16(msg, WPS_UUID_LEN);
789 wpabuf_put_data(msg, wps->uuid_r, WPS_UUID_LEN);
790 return 0;
791}
792
793
ad08c363
JM
794static int wps_build_r_hash(struct wps_data *wps, struct wpabuf *msg)
795{
796 u8 *hash;
797 const u8 *addr[4];
798 size_t len[4];
799
800 if (os_get_random(wps->snonce, 2 * WPS_SECRET_NONCE_LEN) < 0)
801 return -1;
802 wpa_hexdump(MSG_DEBUG, "WPS: R-S1", wps->snonce, WPS_SECRET_NONCE_LEN);
803 wpa_hexdump(MSG_DEBUG, "WPS: R-S2",
804 wps->snonce + WPS_SECRET_NONCE_LEN, WPS_SECRET_NONCE_LEN);
805
806 if (wps->dh_pubkey_e == NULL || wps->dh_pubkey_r == NULL) {
807 wpa_printf(MSG_DEBUG, "WPS: DH public keys not available for "
808 "R-Hash derivation");
809 return -1;
810 }
811
812 wpa_printf(MSG_DEBUG, "WPS: * R-Hash1");
813 wpabuf_put_be16(msg, ATTR_R_HASH1);
814 wpabuf_put_be16(msg, SHA256_MAC_LEN);
815 hash = wpabuf_put(msg, SHA256_MAC_LEN);
816 /* R-Hash1 = HMAC_AuthKey(R-S1 || PSK1 || PK_E || PK_R) */
817 addr[0] = wps->snonce;
818 len[0] = WPS_SECRET_NONCE_LEN;
819 addr[1] = wps->psk1;
820 len[1] = WPS_PSK_LEN;
821 addr[2] = wpabuf_head(wps->dh_pubkey_e);
822 len[2] = wpabuf_len(wps->dh_pubkey_e);
823 addr[3] = wpabuf_head(wps->dh_pubkey_r);
824 len[3] = wpabuf_len(wps->dh_pubkey_r);
825 hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
826 wpa_hexdump(MSG_DEBUG, "WPS: R-Hash1", hash, SHA256_MAC_LEN);
827
828 wpa_printf(MSG_DEBUG, "WPS: * R-Hash2");
829 wpabuf_put_be16(msg, ATTR_R_HASH2);
830 wpabuf_put_be16(msg, SHA256_MAC_LEN);
831 hash = wpabuf_put(msg, SHA256_MAC_LEN);
832 /* R-Hash2 = HMAC_AuthKey(R-S2 || PSK2 || PK_E || PK_R) */
833 addr[0] = wps->snonce + WPS_SECRET_NONCE_LEN;
834 addr[1] = wps->psk2;
835 hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
836 wpa_hexdump(MSG_DEBUG, "WPS: R-Hash2", hash, SHA256_MAC_LEN);
837
838 return 0;
839}
840
841
842static int wps_build_r_snonce1(struct wps_data *wps, struct wpabuf *msg)
843{
844 wpa_printf(MSG_DEBUG, "WPS: * R-SNonce1");
845 wpabuf_put_be16(msg, ATTR_R_SNONCE1);
846 wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN);
847 wpabuf_put_data(msg, wps->snonce, WPS_SECRET_NONCE_LEN);
848 return 0;
849}
850
851
852static int wps_build_r_snonce2(struct wps_data *wps, struct wpabuf *msg)
853{
854 wpa_printf(MSG_DEBUG, "WPS: * R-SNonce2");
855 wpabuf_put_be16(msg, ATTR_R_SNONCE2);
856 wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN);
857 wpabuf_put_data(msg, wps->snonce + WPS_SECRET_NONCE_LEN,
858 WPS_SECRET_NONCE_LEN);
859 return 0;
860}
861
862
3f42d42c
JM
863static int wps_build_cred_network_idx(struct wpabuf *msg,
864 struct wps_credential *cred)
ad08c363
JM
865{
866 wpa_printf(MSG_DEBUG, "WPS: * Network Index");
867 wpabuf_put_be16(msg, ATTR_NETWORK_INDEX);
868 wpabuf_put_be16(msg, 1);
655e4666 869 wpabuf_put_u8(msg, 1);
ad08c363
JM
870 return 0;
871}
872
873
3f42d42c
JM
874static int wps_build_cred_ssid(struct wpabuf *msg,
875 struct wps_credential *cred)
ad08c363
JM
876{
877 wpa_printf(MSG_DEBUG, "WPS: * SSID");
878 wpabuf_put_be16(msg, ATTR_SSID);
3f42d42c
JM
879 wpabuf_put_be16(msg, cred->ssid_len);
880 wpabuf_put_data(msg, cred->ssid, cred->ssid_len);
ad08c363
JM
881 return 0;
882}
883
884
3f42d42c
JM
885static int wps_build_cred_auth_type(struct wpabuf *msg,
886 struct wps_credential *cred)
ad08c363
JM
887{
888 wpa_printf(MSG_DEBUG, "WPS: * Authentication Type (0x%x)",
3f42d42c 889 cred->auth_type);
ad08c363
JM
890 wpabuf_put_be16(msg, ATTR_AUTH_TYPE);
891 wpabuf_put_be16(msg, 2);
3f42d42c 892 wpabuf_put_be16(msg, cred->auth_type);
ad08c363
JM
893 return 0;
894}
895
896
3f42d42c
JM
897static int wps_build_cred_encr_type(struct wpabuf *msg,
898 struct wps_credential *cred)
ad08c363
JM
899{
900 wpa_printf(MSG_DEBUG, "WPS: * Encryption Type (0x%x)",
3f42d42c 901 cred->encr_type);
ad08c363
JM
902 wpabuf_put_be16(msg, ATTR_ENCR_TYPE);
903 wpabuf_put_be16(msg, 2);
3f42d42c 904 wpabuf_put_be16(msg, cred->encr_type);
ad08c363
JM
905 return 0;
906}
907
908
3f42d42c
JM
909static int wps_build_cred_network_key(struct wpabuf *msg,
910 struct wps_credential *cred)
ad08c363
JM
911{
912 wpa_printf(MSG_DEBUG, "WPS: * Network Key");
913 wpabuf_put_be16(msg, ATTR_NETWORK_KEY);
3f42d42c
JM
914 wpabuf_put_be16(msg, cred->key_len);
915 wpabuf_put_data(msg, cred->key, cred->key_len);
ad08c363
JM
916 return 0;
917}
918
919
3f42d42c
JM
920static int wps_build_cred_mac_addr(struct wpabuf *msg,
921 struct wps_credential *cred)
ad08c363 922{
05bf32cc
JM
923 wpa_printf(MSG_DEBUG, "WPS: * MAC Address (" MACSTR ")",
924 MAC2STR(cred->mac_addr));
ad08c363
JM
925 wpabuf_put_be16(msg, ATTR_MAC_ADDR);
926 wpabuf_put_be16(msg, ETH_ALEN);
3f42d42c
JM
927 wpabuf_put_data(msg, cred->mac_addr, ETH_ALEN);
928 return 0;
929}
930
931
932static int wps_build_credential(struct wpabuf *msg,
933 struct wps_credential *cred)
934{
935 if (wps_build_cred_network_idx(msg, cred) ||
936 wps_build_cred_ssid(msg, cred) ||
937 wps_build_cred_auth_type(msg, cred) ||
938 wps_build_cred_encr_type(msg, cred) ||
939 wps_build_cred_network_key(msg, cred) ||
940 wps_build_cred_mac_addr(msg, cred))
941 return -1;
ad08c363
JM
942 return 0;
943}
944
945
946static int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
947{
948 struct wpabuf *cred;
ad08c363 949
6fa68a0e
JM
950 if (wps->wps->registrar->skip_cred_build)
951 goto skip_cred_build;
952
3f42d42c
JM
953 wpa_printf(MSG_DEBUG, "WPS: * Credential");
954 os_memset(&wps->cred, 0, sizeof(wps->cred));
ad08c363 955
3f42d42c
JM
956 os_memcpy(wps->cred.ssid, wps->wps->ssid, wps->wps->ssid_len);
957 wps->cred.ssid_len = wps->wps->ssid_len;
ad08c363
JM
958
959 /* Select the best authentication and encryption type */
960 if (wps->auth_type & WPS_AUTH_WPA2PSK)
961 wps->auth_type = WPS_AUTH_WPA2PSK;
962 else if (wps->auth_type & WPS_AUTH_WPAPSK)
963 wps->auth_type = WPS_AUTH_WPAPSK;
964 else if (wps->auth_type & WPS_AUTH_OPEN)
965 wps->auth_type = WPS_AUTH_OPEN;
966 else if (wps->auth_type & WPS_AUTH_SHARED)
967 wps->auth_type = WPS_AUTH_SHARED;
968 else {
969 wpa_printf(MSG_DEBUG, "WPS: Unsupported auth_type 0x%x",
970 wps->auth_type);
971 return -1;
972 }
3f42d42c 973 wps->cred.auth_type = wps->auth_type;
ad08c363
JM
974
975 if (wps->auth_type == WPS_AUTH_WPA2PSK ||
976 wps->auth_type == WPS_AUTH_WPAPSK) {
977 if (wps->encr_type & WPS_ENCR_AES)
978 wps->encr_type = WPS_ENCR_AES;
979 else if (wps->encr_type & WPS_ENCR_TKIP)
980 wps->encr_type = WPS_ENCR_TKIP;
981 else {
982 wpa_printf(MSG_DEBUG, "WPS: No suitable encryption "
983 "type for WPA/WPA2");
984 return -1;
985 }
986 } else {
987 if (wps->encr_type & WPS_ENCR_WEP)
988 wps->encr_type = WPS_ENCR_WEP;
989 else if (wps->encr_type & WPS_ENCR_NONE)
990 wps->encr_type = WPS_ENCR_NONE;
991 else {
992 wpa_printf(MSG_DEBUG, "WPS: No suitable encryption "
993 "type for non-WPA/WPA2 mode");
994 return -1;
995 }
996 }
3f42d42c 997 wps->cred.encr_type = wps->encr_type;
05bf32cc
JM
998 /* Set MAC address in the Credential to be the AP's address (BSSID) */
999 os_memcpy(wps->cred.mac_addr, wps->wps->dev.mac_addr, ETH_ALEN);
3f42d42c 1000
aabe26a1
JM
1001 if (wps->wps->wps_state == WPS_STATE_NOT_CONFIGURED && wps->wps->ap &&
1002 !wps->wps->registrar->disable_auto_conf) {
3f42d42c
JM
1003 u8 r[16];
1004 /* Generate a random passphrase */
1005 if (os_get_random(r, sizeof(r)) < 0)
1006 return -1;
1007 os_free(wps->new_psk);
1008 wps->new_psk = base64_encode(r, sizeof(r), &wps->new_psk_len);
1009 if (wps->new_psk == NULL)
1010 return -1;
1011 wps->new_psk_len--; /* remove newline */
1012 while (wps->new_psk_len &&
1013 wps->new_psk[wps->new_psk_len - 1] == '=')
1014 wps->new_psk_len--;
1015 wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Generated passphrase",
1016 wps->new_psk, wps->new_psk_len);
1017 os_memcpy(wps->cred.key, wps->new_psk, wps->new_psk_len);
1018 wps->cred.key_len = wps->new_psk_len;
1019 } else if (wps->wps->network_key) {
1020 os_memcpy(wps->cred.key, wps->wps->network_key,
1021 wps->wps->network_key_len);
1022 wps->cred.key_len = wps->wps->network_key_len;
1023 } else if (wps->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) {
1024 char hex[65];
1025 /* Generate a random per-device PSK */
1026 os_free(wps->new_psk);
1027 wps->new_psk_len = 32;
1028 wps->new_psk = os_malloc(wps->new_psk_len);
1029 if (wps->new_psk == NULL)
1030 return -1;
1031 if (os_get_random(wps->new_psk, wps->new_psk_len) < 0) {
1032 os_free(wps->new_psk);
1033 wps->new_psk = NULL;
1034 return -1;
1035 }
1036 wpa_hexdump_key(MSG_DEBUG, "WPS: Generated per-device PSK",
1037 wps->new_psk, wps->new_psk_len);
1038 wpa_snprintf_hex(hex, sizeof(hex), wps->new_psk,
1039 wps->new_psk_len);
1040 os_memcpy(wps->cred.key, hex, wps->new_psk_len * 2);
1041 wps->cred.key_len = wps->new_psk_len * 2;
1042 }
ad08c363
JM
1043
1044 cred = wpabuf_alloc(200);
1045 if (cred == NULL)
1046 return -1;
1047
3f42d42c 1048 if (wps_build_credential(cred, &wps->cred)) {
ad08c363
JM
1049 wpabuf_free(cred);
1050 return -1;
1051 }
1052
3f42d42c
JM
1053 wpabuf_put_be16(msg, ATTR_CRED);
1054 wpabuf_put_be16(msg, wpabuf_len(cred));
1055 wpabuf_put_buf(msg, cred);
1056 wpabuf_free(cred);
1057
6fa68a0e
JM
1058skip_cred_build:
1059 if (wps->wps->registrar->extra_cred) {
1060 wpa_printf(MSG_DEBUG, "WPS: * Credential (pre-configured)");
1061 wpabuf_put_buf(msg, wps->wps->registrar->extra_cred);
1062 }
1063
3f42d42c
JM
1064 return 0;
1065}
1066
1067
1068static int wps_build_ap_settings(struct wps_data *wps, struct wpabuf *msg)
1069{
1070 wpa_printf(MSG_DEBUG, "WPS: * AP Settings");
1071
1072 if (wps_build_credential(msg, &wps->cred))
1073 return -1;
ad08c363
JM
1074
1075 return 0;
1076}
1077
1078
1079static struct wpabuf * wps_build_m2(struct wps_data *wps)
1080{
1081 struct wpabuf *msg;
1082
1083 if (os_get_random(wps->nonce_r, WPS_NONCE_LEN) < 0)
1084 return NULL;
1085 wpa_hexdump(MSG_DEBUG, "WPS: Registrar Nonce",
1086 wps->nonce_r, WPS_NONCE_LEN);
ad08c363
JM
1087 wpa_hexdump(MSG_DEBUG, "WPS: UUID-R", wps->uuid_r, WPS_UUID_LEN);
1088
1089 wpa_printf(MSG_DEBUG, "WPS: Building Message M2");
1090 msg = wpabuf_alloc(1000);
1091 if (msg == NULL)
1092 return NULL;
1093
1094 if (wps_build_version(msg) ||
1095 wps_build_msg_type(msg, WPS_M2) ||
1096 wps_build_enrollee_nonce(wps, msg) ||
1097 wps_build_registrar_nonce(wps, msg) ||
1098 wps_build_uuid_r(wps, msg) ||
1099 wps_build_public_key(wps, msg) ||
1100 wps_derive_keys(wps) ||
1101 wps_build_auth_type_flags(wps, msg) ||
1102 wps_build_encr_type_flags(wps, msg) ||
1103 wps_build_conn_type_flags(wps, msg) ||
41c00105 1104 wps_build_config_methods_r(wps->wps->registrar, msg) ||
ad08c363 1105 wps_build_device_attrs(&wps->wps->dev, msg) ||
120bd30c 1106 wps_build_rf_bands(&wps->wps->dev, msg) ||
ad08c363 1107 wps_build_assoc_state(wps, msg) ||
c0d041d9
JM
1108 wps_build_config_error(msg, WPS_CFG_NO_ERROR) ||
1109 wps_build_dev_password_id(msg, DEV_PW_DEFAULT) ||
ad08c363
JM
1110 wps_build_os_version(&wps->wps->dev, msg) ||
1111 wps_build_authenticator(wps, msg)) {
1112 wpabuf_free(msg);
1113 return NULL;
1114 }
1115
1116 wps->state = RECV_M3;
1117 return msg;
1118}
1119
1120
1121static struct wpabuf * wps_build_m2d(struct wps_data *wps)
1122{
1123 struct wpabuf *msg;
c0d041d9 1124 u16 err = WPS_CFG_NO_ERROR;
ad08c363
JM
1125
1126 wpa_printf(MSG_DEBUG, "WPS: Building Message M2D");
1127 msg = wpabuf_alloc(1000);
1128 if (msg == NULL)
1129 return NULL;
1130
5a8c6d33 1131 if (wps->wps->ap && wps->wps->ap_setup_locked)
c0d041d9
JM
1132 err = WPS_CFG_SETUP_LOCKED;
1133
ad08c363
JM
1134 if (wps_build_version(msg) ||
1135 wps_build_msg_type(msg, WPS_M2D) ||
1136 wps_build_enrollee_nonce(wps, msg) ||
1137 wps_build_registrar_nonce(wps, msg) ||
1138 wps_build_uuid_r(wps, msg) ||
1139 wps_build_auth_type_flags(wps, msg) ||
1140 wps_build_encr_type_flags(wps, msg) ||
1141 wps_build_conn_type_flags(wps, msg) ||
41c00105 1142 wps_build_config_methods_r(wps->wps->registrar, msg) ||
ad08c363 1143 wps_build_device_attrs(&wps->wps->dev, msg) ||
120bd30c 1144 wps_build_rf_bands(&wps->wps->dev, msg) ||
ad08c363 1145 wps_build_assoc_state(wps, msg) ||
c0d041d9 1146 wps_build_config_error(msg, err) ||
ad08c363
JM
1147 wps_build_os_version(&wps->wps->dev, msg)) {
1148 wpabuf_free(msg);
1149 return NULL;
1150 }
1151
1152 wps->state = RECV_M2D_ACK;
1153 return msg;
1154}
1155
1156
1157static struct wpabuf * wps_build_m4(struct wps_data *wps)
1158{
1159 struct wpabuf *msg, *plain;
1160
1161 wpa_printf(MSG_DEBUG, "WPS: Building Message M4");
1162
1163 wps_derive_psk(wps, wps->dev_password, wps->dev_password_len);
1164
1165 plain = wpabuf_alloc(200);
1166 if (plain == NULL)
1167 return NULL;
1168
1169 msg = wpabuf_alloc(1000);
1170 if (msg == NULL) {
1171 wpabuf_free(plain);
1172 return NULL;
1173 }
1174
1175 if (wps_build_version(msg) ||
1176 wps_build_msg_type(msg, WPS_M4) ||
1177 wps_build_enrollee_nonce(wps, msg) ||
1178 wps_build_r_hash(wps, msg) ||
1179 wps_build_r_snonce1(wps, plain) ||
1180 wps_build_key_wrap_auth(wps, plain) ||
1181 wps_build_encr_settings(wps, msg, plain) ||
1182 wps_build_authenticator(wps, msg)) {
1183 wpabuf_free(plain);
1184 wpabuf_free(msg);
1185 return NULL;
1186 }
1187 wpabuf_free(plain);
1188
1189 wps->state = RECV_M5;
1190 return msg;
1191}
1192
1193
1194static struct wpabuf * wps_build_m6(struct wps_data *wps)
1195{
1196 struct wpabuf *msg, *plain;
1197
1198 wpa_printf(MSG_DEBUG, "WPS: Building Message M6");
1199
1200 plain = wpabuf_alloc(200);
1201 if (plain == NULL)
1202 return NULL;
1203
1204 msg = wpabuf_alloc(1000);
1205 if (msg == NULL) {
1206 wpabuf_free(plain);
1207 return NULL;
1208 }
1209
1210 if (wps_build_version(msg) ||
1211 wps_build_msg_type(msg, WPS_M6) ||
1212 wps_build_enrollee_nonce(wps, msg) ||
1213 wps_build_r_snonce2(wps, plain) ||
1214 wps_build_key_wrap_auth(wps, plain) ||
1215 wps_build_encr_settings(wps, msg, plain) ||
1216 wps_build_authenticator(wps, msg)) {
1217 wpabuf_free(plain);
1218 wpabuf_free(msg);
1219 return NULL;
1220 }
1221 wpabuf_free(plain);
1222
1223 wps->wps_pin_revealed = 1;
1224 wps->state = RECV_M7;
1225 return msg;
1226}
1227
1228
1229static struct wpabuf * wps_build_m8(struct wps_data *wps)
1230{
1231 struct wpabuf *msg, *plain;
1232
1233 wpa_printf(MSG_DEBUG, "WPS: Building Message M8");
1234
1235 plain = wpabuf_alloc(500);
1236 if (plain == NULL)
1237 return NULL;
1238
1239 msg = wpabuf_alloc(1000);
1240 if (msg == NULL) {
1241 wpabuf_free(plain);
1242 return NULL;
1243 }
1244
1245 if (wps_build_version(msg) ||
1246 wps_build_msg_type(msg, WPS_M8) ||
1247 wps_build_enrollee_nonce(wps, msg) ||
3f42d42c
JM
1248 (wps->wps->ap && wps_build_cred(wps, plain)) ||
1249 (!wps->wps->ap && wps_build_ap_settings(wps, plain)) ||
ad08c363
JM
1250 wps_build_key_wrap_auth(wps, plain) ||
1251 wps_build_encr_settings(wps, msg, plain) ||
1252 wps_build_authenticator(wps, msg)) {
1253 wpabuf_free(plain);
1254 wpabuf_free(msg);
1255 return NULL;
1256 }
1257 wpabuf_free(plain);
1258
1259 wps->state = RECV_DONE;
1260 return msg;
1261}
1262
1263
1264static struct wpabuf * wps_build_wsc_ack(struct wps_data *wps)
1265{
1266 struct wpabuf *msg;
1267
1268 wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_ACK");
1269
1270 msg = wpabuf_alloc(1000);
1271 if (msg == NULL)
1272 return NULL;
1273
1274 if (wps_build_version(msg) ||
1275 wps_build_msg_type(msg, WPS_WSC_ACK) ||
1276 wps_build_enrollee_nonce(wps, msg) ||
1277 wps_build_registrar_nonce(wps, msg)) {
1278 wpabuf_free(msg);
1279 return NULL;
1280 }
1281
1282 return msg;
1283}
1284
1285
a92c421d
JM
1286static struct wpabuf * wps_build_wsc_nack(struct wps_data *wps)
1287{
1288 struct wpabuf *msg;
1289
1290 wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_NACK");
1291
1292 msg = wpabuf_alloc(1000);
1293 if (msg == NULL)
1294 return NULL;
1295
1296 if (wps_build_version(msg) ||
1297 wps_build_msg_type(msg, WPS_WSC_NACK) ||
1298 wps_build_enrollee_nonce(wps, msg) ||
1299 wps_build_registrar_nonce(wps, msg) ||
1300 wps_build_config_error(msg, wps->config_error)) {
1301 wpabuf_free(msg);
1302 return NULL;
1303 }
1304
1305 return msg;
1306}
1307
1308
f90c86d4
JM
1309struct wpabuf * wps_registrar_get_msg(struct wps_data *wps,
1310 enum wsc_op_code *op_code)
ad08c363
JM
1311{
1312 struct wpabuf *msg;
1313
1314 switch (wps->state) {
1315 case SEND_M2:
1316 if (wps_get_dev_password(wps) < 0)
1317 msg = wps_build_m2d(wps);
1318 else
1319 msg = wps_build_m2(wps);
1320 *op_code = WSC_MSG;
1321 break;
1322 case SEND_M2D:
1323 msg = wps_build_m2d(wps);
1324 *op_code = WSC_MSG;
1325 break;
1326 case SEND_M4:
1327 msg = wps_build_m4(wps);
1328 *op_code = WSC_MSG;
1329 break;
1330 case SEND_M6:
1331 msg = wps_build_m6(wps);
1332 *op_code = WSC_MSG;
1333 break;
1334 case SEND_M8:
1335 msg = wps_build_m8(wps);
1336 *op_code = WSC_MSG;
1337 break;
1338 case RECV_DONE:
1339 msg = wps_build_wsc_ack(wps);
1340 *op_code = WSC_ACK;
1341 break;
a92c421d
JM
1342 case SEND_WSC_NACK:
1343 msg = wps_build_wsc_nack(wps);
1344 *op_code = WSC_NACK;
1345 break;
ad08c363
JM
1346 default:
1347 wpa_printf(MSG_DEBUG, "WPS: Unsupported state %d for building "
1348 "a message", wps->state);
1349 msg = NULL;
1350 break;
1351 }
1352
1353 if (*op_code == WSC_MSG && msg) {
1354 /* Save a copy of the last message for Authenticator derivation
1355 */
1356 wpabuf_free(wps->last_msg);
1357 wps->last_msg = wpabuf_dup(msg);
1358 }
1359
1360 return msg;
1361}
1362
1363
1364static int wps_process_enrollee_nonce(struct wps_data *wps, const u8 *e_nonce)
1365{
1366 if (e_nonce == NULL) {
1367 wpa_printf(MSG_DEBUG, "WPS: No Enrollee Nonce received");
1368 return -1;
1369 }
1370
1371 os_memcpy(wps->nonce_e, e_nonce, WPS_NONCE_LEN);
1372 wpa_hexdump(MSG_DEBUG, "WPS: Enrollee Nonce",
1373 wps->nonce_e, WPS_NONCE_LEN);
1374
1375 return 0;
1376}
1377
1378
1379static int wps_process_registrar_nonce(struct wps_data *wps, const u8 *r_nonce)
1380{
1381 if (r_nonce == NULL) {
1382 wpa_printf(MSG_DEBUG, "WPS: No Registrar Nonce received");
1383 return -1;
1384 }
1385
1386 if (os_memcmp(wps->nonce_r, r_nonce, WPS_NONCE_LEN) != 0) {
1387 wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce received");
1388 return -1;
1389 }
1390
1391 return 0;
1392}
1393
1394
1395static int wps_process_uuid_e(struct wps_data *wps, const u8 *uuid_e)
1396{
1397 if (uuid_e == NULL) {
1398 wpa_printf(MSG_DEBUG, "WPS: No UUID-E received");
1399 return -1;
1400 }
1401
1402 os_memcpy(wps->uuid_e, uuid_e, WPS_UUID_LEN);
1403 wpa_hexdump(MSG_DEBUG, "WPS: UUID-E", wps->uuid_e, WPS_UUID_LEN);
1404
1405 return 0;
1406}
1407
1408
1409static int wps_process_dev_password_id(struct wps_data *wps, const u8 *pw_id)
1410{
1411 if (pw_id == NULL) {
1412 wpa_printf(MSG_DEBUG, "WPS: No Device Password ID received");
1413 return -1;
1414 }
1415
1416 wps->dev_pw_id = WPA_GET_BE16(pw_id);
1417 wpa_printf(MSG_DEBUG, "WPS: Device Password ID %d", wps->dev_pw_id);
1418
1419 return 0;
1420}
1421
1422
1423static int wps_process_e_hash1(struct wps_data *wps, const u8 *e_hash1)
1424{
1425 if (e_hash1 == NULL) {
1426 wpa_printf(MSG_DEBUG, "WPS: No E-Hash1 received");
1427 return -1;
1428 }
1429
1430 os_memcpy(wps->peer_hash1, e_hash1, WPS_HASH_LEN);
1431 wpa_hexdump(MSG_DEBUG, "WPS: E-Hash1", wps->peer_hash1, WPS_HASH_LEN);
1432
1433 return 0;
1434}
1435
1436
1437static int wps_process_e_hash2(struct wps_data *wps, const u8 *e_hash2)
1438{
1439 if (e_hash2 == NULL) {
1440 wpa_printf(MSG_DEBUG, "WPS: No E-Hash2 received");
1441 return -1;
1442 }
1443
1444 os_memcpy(wps->peer_hash2, e_hash2, WPS_HASH_LEN);
1445 wpa_hexdump(MSG_DEBUG, "WPS: E-Hash2", wps->peer_hash2, WPS_HASH_LEN);
1446
1447 return 0;
1448}
1449
1450
1451static int wps_process_e_snonce1(struct wps_data *wps, const u8 *e_snonce1)
1452{
1453 u8 hash[SHA256_MAC_LEN];
1454 const u8 *addr[4];
1455 size_t len[4];
1456
1457 if (e_snonce1 == NULL) {
1458 wpa_printf(MSG_DEBUG, "WPS: No E-SNonce1 received");
1459 return -1;
1460 }
1461
1462 wpa_hexdump_key(MSG_DEBUG, "WPS: E-SNonce1", e_snonce1,
1463 WPS_SECRET_NONCE_LEN);
1464
1465 /* E-Hash1 = HMAC_AuthKey(E-S1 || PSK1 || PK_E || PK_R) */
1466 addr[0] = e_snonce1;
1467 len[0] = WPS_SECRET_NONCE_LEN;
1468 addr[1] = wps->psk1;
1469 len[1] = WPS_PSK_LEN;
1470 addr[2] = wpabuf_head(wps->dh_pubkey_e);
1471 len[2] = wpabuf_len(wps->dh_pubkey_e);
1472 addr[3] = wpabuf_head(wps->dh_pubkey_r);
1473 len[3] = wpabuf_len(wps->dh_pubkey_r);
1474 hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
1475
1476 if (os_memcmp(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) {
1477 wpa_printf(MSG_DEBUG, "WPS: E-Hash1 derived from E-S1 does "
1478 "not match with the pre-committed value");
a92c421d 1479 wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE;
ad08c363
JM
1480 return -1;
1481 }
1482
1483 wpa_printf(MSG_DEBUG, "WPS: Enrollee proved knowledge of the first "
1484 "half of the device password");
1485
1486 return 0;
1487}
1488
1489
1490static int wps_process_e_snonce2(struct wps_data *wps, const u8 *e_snonce2)
1491{
1492 u8 hash[SHA256_MAC_LEN];
1493 const u8 *addr[4];
1494 size_t len[4];
1495
1496 if (e_snonce2 == NULL) {
1497 wpa_printf(MSG_DEBUG, "WPS: No E-SNonce2 received");
1498 return -1;
1499 }
1500
1501 wpa_hexdump_key(MSG_DEBUG, "WPS: E-SNonce2", e_snonce2,
1502 WPS_SECRET_NONCE_LEN);
1503
1504 /* E-Hash2 = HMAC_AuthKey(E-S2 || PSK2 || PK_E || PK_R) */
1505 addr[0] = e_snonce2;
1506 len[0] = WPS_SECRET_NONCE_LEN;
1507 addr[1] = wps->psk2;
1508 len[1] = WPS_PSK_LEN;
1509 addr[2] = wpabuf_head(wps->dh_pubkey_e);
1510 len[2] = wpabuf_len(wps->dh_pubkey_e);
1511 addr[3] = wpabuf_head(wps->dh_pubkey_r);
1512 len[3] = wpabuf_len(wps->dh_pubkey_r);
1513 hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
1514
1515 if (os_memcmp(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) {
1516 wpa_printf(MSG_DEBUG, "WPS: E-Hash2 derived from E-S2 does "
1517 "not match with the pre-committed value");
41c00105 1518 wps_registrar_invalidate_pin(wps->wps->registrar, wps->uuid_e);
a92c421d 1519 wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE;
ad08c363
JM
1520 return -1;
1521 }
1522
1523 wpa_printf(MSG_DEBUG, "WPS: Enrollee proved knowledge of the second "
1524 "half of the device password");
1525 wps->wps_pin_revealed = 0;
41c00105 1526 wps_registrar_unlock_pin(wps->wps->registrar, wps->uuid_e);
ad08c363
JM
1527
1528 return 0;
1529}
1530
1531
1532static int wps_process_mac_addr(struct wps_data *wps, const u8 *mac_addr)
1533{
1534 if (mac_addr == NULL) {
1535 wpa_printf(MSG_DEBUG, "WPS: No MAC Address received");
1536 return -1;
1537 }
1538
1539 wpa_printf(MSG_DEBUG, "WPS: Enrollee MAC Address " MACSTR,
1540 MAC2STR(mac_addr));
1541 os_memcpy(wps->mac_addr_e, mac_addr, ETH_ALEN);
1542 os_memcpy(wps->peer_dev.mac_addr, mac_addr, ETH_ALEN);
1543
1544 return 0;
1545}
1546
1547
1548static int wps_process_pubkey(struct wps_data *wps, const u8 *pk,
1549 size_t pk_len)
1550{
1551 if (pk == NULL || pk_len == 0) {
1552 wpa_printf(MSG_DEBUG, "WPS: No Public Key received");
1553 return -1;
1554 }
1555
1556 wpabuf_free(wps->dh_pubkey_e);
1557 wps->dh_pubkey_e = wpabuf_alloc_copy(pk, pk_len);
1558 if (wps->dh_pubkey_e == NULL)
1559 return -1;
1560
1561 return 0;
1562}
1563
1564
1565static int wps_process_auth_type_flags(struct wps_data *wps, const u8 *auth)
1566{
1567 u16 auth_types;
1568
1569 if (auth == NULL) {
1570 wpa_printf(MSG_DEBUG, "WPS: No Authentication Type flags "
1571 "received");
1572 return -1;
1573 }
1574
1575 auth_types = WPA_GET_BE16(auth);
1576
1577 wpa_printf(MSG_DEBUG, "WPS: Enrollee Authentication Type flags 0x%x",
1578 auth_types);
1579 wps->auth_type = wps->wps->auth_types & auth_types;
1580 if (wps->auth_type == 0) {
1581 wpa_printf(MSG_DEBUG, "WPS: No match in supported "
79d7d8ef
JM
1582 "authentication types (own 0x%x Enrollee 0x%x)",
1583 wps->wps->auth_types, auth_types);
ad08c363
JM
1584 return -1;
1585 }
1586
1587 return 0;
1588}
1589
1590
1591static int wps_process_encr_type_flags(struct wps_data *wps, const u8 *encr)
1592{
1593 u16 encr_types;
1594
1595 if (encr == NULL) {
1596 wpa_printf(MSG_DEBUG, "WPS: No Encryption Type flags "
1597 "received");
1598 return -1;
1599 }
1600
1601 encr_types = WPA_GET_BE16(encr);
1602
1603 wpa_printf(MSG_DEBUG, "WPS: Enrollee Encryption Type flags 0x%x",
1604 encr_types);
1605 wps->encr_type = wps->wps->encr_types & encr_types;
1606 if (wps->encr_type == 0) {
1607 wpa_printf(MSG_DEBUG, "WPS: No match in supported "
1608 "encryption types");
1609 return -1;
1610 }
1611
1612 return 0;
1613}
1614
1615
1616static int wps_process_conn_type_flags(struct wps_data *wps, const u8 *conn)
1617{
1618 if (conn == NULL) {
1619 wpa_printf(MSG_DEBUG, "WPS: No Connection Type flags "
1620 "received");
1621 return -1;
1622 }
1623
1624 wpa_printf(MSG_DEBUG, "WPS: Enrollee Connection Type flags 0x%x",
1625 *conn);
1626
1627 return 0;
1628}
1629
1630
1631static int wps_process_config_methods(struct wps_data *wps, const u8 *methods)
1632{
1633 u16 m;
1634
1635 if (methods == NULL) {
1636 wpa_printf(MSG_DEBUG, "WPS: No Config Methods received");
1637 return -1;
1638 }
1639
1640 m = WPA_GET_BE16(methods);
1641
1642 wpa_printf(MSG_DEBUG, "WPS: Enrollee Config Methods 0x%x", m);
1643
1644 return 0;
1645}
1646
1647
1648static int wps_process_wps_state(struct wps_data *wps, const u8 *state)
1649{
1650 if (state == NULL) {
1651 wpa_printf(MSG_DEBUG, "WPS: No Wi-Fi Protected Setup State "
1652 "received");
1653 return -1;
1654 }
1655
1656 wpa_printf(MSG_DEBUG, "WPS: Enrollee Wi-Fi Protected Setup State %d",
1657 *state);
1658
1659 return 0;
1660}
1661
1662
ad08c363
JM
1663static int wps_process_assoc_state(struct wps_data *wps, const u8 *assoc)
1664{
1665 u16 a;
1666
1667 if (assoc == NULL) {
1668 wpa_printf(MSG_DEBUG, "WPS: No Association State received");
1669 return -1;
1670 }
1671
1672 a = WPA_GET_BE16(assoc);
1673 wpa_printf(MSG_DEBUG, "WPS: Enrollee Association State %d", a);
1674
1675 return 0;
1676}
1677
1678
1679static int wps_process_config_error(struct wps_data *wps, const u8 *err)
1680{
1681 u16 e;
1682
1683 if (err == NULL) {
1684 wpa_printf(MSG_DEBUG, "WPS: No Configuration Error received");
1685 return -1;
1686 }
1687
1688 e = WPA_GET_BE16(err);
1689 wpa_printf(MSG_DEBUG, "WPS: Enrollee Configuration Error %d", e);
1690
1691 return 0;
1692}
1693
1694
1695static enum wps_process_res wps_process_m1(struct wps_data *wps,
1696 struct wps_parse_attr *attr)
1697{
1698 wpa_printf(MSG_DEBUG, "WPS: Received M1");
1699
1700 if (wps->state != RECV_M1) {
1701 wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
1702 "receiving M1", wps->state);
1703 return WPS_FAILURE;
1704 }
1705
1706 if (wps_process_uuid_e(wps, attr->uuid_e) ||
1707 wps_process_mac_addr(wps, attr->mac_addr) ||
1708 wps_process_enrollee_nonce(wps, attr->enrollee_nonce) ||
1709 wps_process_pubkey(wps, attr->public_key, attr->public_key_len) ||
1710 wps_process_auth_type_flags(wps, attr->auth_type_flags) ||
1711 wps_process_encr_type_flags(wps, attr->encr_type_flags) ||
1712 wps_process_conn_type_flags(wps, attr->conn_type_flags) ||
1713 wps_process_config_methods(wps, attr->config_methods) ||
1714 wps_process_wps_state(wps, attr->wps_state) ||
1715 wps_process_device_attrs(&wps->peer_dev, attr) ||
120bd30c 1716 wps_process_rf_bands(&wps->peer_dev, attr->rf_bands) ||
ad08c363
JM
1717 wps_process_assoc_state(wps, attr->assoc_state) ||
1718 wps_process_dev_password_id(wps, attr->dev_password_id) ||
1719 wps_process_config_error(wps, attr->config_error) ||
1720 wps_process_os_version(&wps->peer_dev, attr->os_version))
1721 return WPS_FAILURE;
1722
1723 if (wps->dev_pw_id != DEV_PW_DEFAULT &&
1724 wps->dev_pw_id != DEV_PW_USER_SPECIFIED &&
1725 wps->dev_pw_id != DEV_PW_MACHINE_SPECIFIED &&
1726 wps->dev_pw_id != DEV_PW_REGISTRAR_SPECIFIED &&
41c00105
JM
1727 (wps->dev_pw_id != DEV_PW_PUSHBUTTON ||
1728 !wps->wps->registrar->pbc)) {
ad08c363
JM
1729 wpa_printf(MSG_DEBUG, "WPS: Unsupported Device Password ID %d",
1730 wps->dev_pw_id);
1731 wps->state = SEND_M2D;
1732 return WPS_CONTINUE;
1733 }
1734
1735 if (wps->dev_pw_id == DEV_PW_PUSHBUTTON) {
41c00105
JM
1736 if (wps_registrar_pbc_overlap(wps->wps->registrar,
1737 wps->mac_addr_e, wps->uuid_e)) {
ad08c363
JM
1738 wpa_printf(MSG_DEBUG, "WPS: PBC overlap - deny PBC "
1739 "negotiation");
1740 wps->state = SEND_M2D;
1741 return WPS_CONTINUE;
1742 }
41c00105
JM
1743 wps_registrar_add_pbc_session(wps->wps->registrar,
1744 wps->mac_addr_e, wps->uuid_e);
ad08c363
JM
1745 wps->pbc = 1;
1746 }
1747
1748 wps->state = SEND_M2;
1749 return WPS_CONTINUE;
1750}
1751
1752
1753static enum wps_process_res wps_process_m3(struct wps_data *wps,
1754 const struct wpabuf *msg,
1755 struct wps_parse_attr *attr)
1756{
1757 wpa_printf(MSG_DEBUG, "WPS: Received M3");
1758
1759 if (wps->state != RECV_M3) {
1760 wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
1761 "receiving M3", wps->state);
a92c421d
JM
1762 wps->state = SEND_WSC_NACK;
1763 return WPS_CONTINUE;
ad08c363
JM
1764 }
1765
1766 if (wps_process_registrar_nonce(wps, attr->registrar_nonce) ||
1767 wps_process_authenticator(wps, attr->authenticator, msg) ||
1768 wps_process_e_hash1(wps, attr->e_hash1) ||
a92c421d
JM
1769 wps_process_e_hash2(wps, attr->e_hash2)) {
1770 wps->state = SEND_WSC_NACK;
1771 return WPS_CONTINUE;
1772 }
ad08c363
JM
1773
1774 wps->state = SEND_M4;
1775 return WPS_CONTINUE;
1776}
1777
1778
1779static enum wps_process_res wps_process_m5(struct wps_data *wps,
1780 const struct wpabuf *msg,
1781 struct wps_parse_attr *attr)
1782{
1783 struct wpabuf *decrypted;
1784 struct wps_parse_attr eattr;
1785
1786 wpa_printf(MSG_DEBUG, "WPS: Received M5");
1787
1788 if (wps->state != RECV_M5) {
1789 wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
1790 "receiving M5", wps->state);
a92c421d
JM
1791 wps->state = SEND_WSC_NACK;
1792 return WPS_CONTINUE;
ad08c363
JM
1793 }
1794
1795 if (wps_process_registrar_nonce(wps, attr->registrar_nonce) ||
a92c421d
JM
1796 wps_process_authenticator(wps, attr->authenticator, msg)) {
1797 wps->state = SEND_WSC_NACK;
1798 return WPS_CONTINUE;
1799 }
ad08c363
JM
1800
1801 decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings,
1802 attr->encr_settings_len);
1803 if (decrypted == NULL) {
1804 wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted "
1805 "Settings attribute");
a92c421d
JM
1806 wps->state = SEND_WSC_NACK;
1807 return WPS_CONTINUE;
ad08c363
JM
1808 }
1809
1810 wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings "
1811 "attribute");
1812 if (wps_parse_msg(decrypted, &eattr) < 0 ||
1813 wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
1814 wps_process_e_snonce1(wps, eattr.e_snonce1)) {
1815 wpabuf_free(decrypted);
a92c421d
JM
1816 wps->state = SEND_WSC_NACK;
1817 return WPS_CONTINUE;
ad08c363
JM
1818 }
1819 wpabuf_free(decrypted);
1820
1821 wps->state = SEND_M6;
1822 return WPS_CONTINUE;
1823}
1824
1825
96a2ed9f
JM
1826static int wps_process_ap_settings_r(struct wps_data *wps,
1827 struct wps_parse_attr *attr)
1828{
96a2ed9f
JM
1829 if (wps->wps->ap)
1830 return 0;
1831
1832 /* AP Settings Attributes in M7 when Enrollee is an AP */
3f42d42c 1833 if (wps_process_ap_settings(attr, &wps->cred) < 0)
96a2ed9f
JM
1834 return -1;
1835
1836 wpa_printf(MSG_INFO, "WPS: Received old AP configuration from AP");
1837
1838 /*
1839 * TODO: Provide access to AP settings and allow changes before sending
1840 * out M8. For now, just copy the settings unchanged into M8.
1841 */
96a2ed9f
JM
1842
1843 return 0;
1844}
1845
1846
ad08c363
JM
1847static enum wps_process_res wps_process_m7(struct wps_data *wps,
1848 const struct wpabuf *msg,
1849 struct wps_parse_attr *attr)
1850{
1851 struct wpabuf *decrypted;
1852 struct wps_parse_attr eattr;
1853
1854 wpa_printf(MSG_DEBUG, "WPS: Received M7");
1855
1856 if (wps->state != RECV_M7) {
1857 wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
1858 "receiving M7", wps->state);
a92c421d
JM
1859 wps->state = SEND_WSC_NACK;
1860 return WPS_CONTINUE;
ad08c363
JM
1861 }
1862
1863 if (wps_process_registrar_nonce(wps, attr->registrar_nonce) ||
a92c421d
JM
1864 wps_process_authenticator(wps, attr->authenticator, msg)) {
1865 wps->state = SEND_WSC_NACK;
1866 return WPS_CONTINUE;
1867 }
ad08c363
JM
1868
1869 decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings,
1870 attr->encr_settings_len);
1871 if (decrypted == NULL) {
1872 wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted "
1873 "Settings attribute");
a92c421d
JM
1874 wps->state = SEND_WSC_NACK;
1875 return WPS_CONTINUE;
ad08c363
JM
1876 }
1877
1878 wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings "
1879 "attribute");
1880 if (wps_parse_msg(decrypted, &eattr) < 0 ||
1881 wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
96a2ed9f
JM
1882 wps_process_e_snonce2(wps, eattr.e_snonce2) ||
1883 wps_process_ap_settings_r(wps, &eattr)) {
ad08c363 1884 wpabuf_free(decrypted);
a92c421d
JM
1885 wps->state = SEND_WSC_NACK;
1886 return WPS_CONTINUE;
ad08c363 1887 }
96a2ed9f 1888
ad08c363
JM
1889 wpabuf_free(decrypted);
1890
1891 wps->state = SEND_M8;
1892 return WPS_CONTINUE;
1893}
1894
1895
1896static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps,
1897 const struct wpabuf *msg)
1898{
1899 struct wps_parse_attr attr;
1900 enum wps_process_res ret = WPS_CONTINUE;
1901
1902 wpa_printf(MSG_DEBUG, "WPS: Received WSC_MSG");
1903
1904 if (wps_parse_msg(msg, &attr) < 0)
1905 return WPS_FAILURE;
1906
1907 if (attr.version == NULL || *attr.version != WPS_VERSION) {
1908 wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x",
1909 attr.version ? *attr.version : 0);
1910 return WPS_FAILURE;
1911 }
1912
1913 if (attr.msg_type == NULL) {
1914 wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
1915 return WPS_FAILURE;
1916 }
1917
1918 if (*attr.msg_type != WPS_M1 &&
1919 (attr.registrar_nonce == NULL ||
1920 os_memcmp(wps->nonce_r, attr.registrar_nonce,
1921 WPS_NONCE_LEN != 0))) {
1922 wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce");
1923 return WPS_FAILURE;
1924 }
1925
1926 switch (*attr.msg_type) {
1927 case WPS_M1:
1928 ret = wps_process_m1(wps, &attr);
1929 break;
1930 case WPS_M3:
1931 ret = wps_process_m3(wps, msg, &attr);
469fc3a4
JM
1932 if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
1933 wps_fail_event(wps->wps, WPS_M3);
ad08c363
JM
1934 break;
1935 case WPS_M5:
1936 ret = wps_process_m5(wps, msg, &attr);
469fc3a4
JM
1937 if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
1938 wps_fail_event(wps->wps, WPS_M5);
ad08c363
JM
1939 break;
1940 case WPS_M7:
1941 ret = wps_process_m7(wps, msg, &attr);
469fc3a4
JM
1942 if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
1943 wps_fail_event(wps->wps, WPS_M7);
ad08c363
JM
1944 break;
1945 default:
1946 wpa_printf(MSG_DEBUG, "WPS: Unsupported Message Type %d",
1947 *attr.msg_type);
1948 return WPS_FAILURE;
1949 }
1950
1951 if (ret == WPS_CONTINUE) {
1952 /* Save a copy of the last message for Authenticator derivation
1953 */
1954 wpabuf_free(wps->last_msg);
1955 wps->last_msg = wpabuf_dup(msg);
1956 }
1957
1958 return ret;
1959}
1960
1961
1962static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps,
1963 const struct wpabuf *msg)
1964{
1965 struct wps_parse_attr attr;
1966
1967 wpa_printf(MSG_DEBUG, "WPS: Received WSC_ACK");
1968
1969 if (wps_parse_msg(msg, &attr) < 0)
1970 return WPS_FAILURE;
1971
1972 if (attr.version == NULL || *attr.version != WPS_VERSION) {
1973 wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x",
1974 attr.version ? *attr.version : 0);
1975 return WPS_FAILURE;
1976 }
1977
1978 if (attr.msg_type == NULL) {
1979 wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
1980 return WPS_FAILURE;
1981 }
1982
1983 if (*attr.msg_type != WPS_WSC_ACK) {
1984 wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d",
1985 *attr.msg_type);
1986 return WPS_FAILURE;
1987 }
1988
1989 if (attr.registrar_nonce == NULL ||
1990 os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN != 0))
1991 {
1992 wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce");
1993 return WPS_FAILURE;
1994 }
1995
1996 if (attr.enrollee_nonce == NULL ||
1997 os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) {
1998 wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce");
1999 return WPS_FAILURE;
2000 }
2001
2002 if (wps->state == RECV_M2D_ACK) {
2003 /* TODO: support for multiple registrars and sending of
2004 * multiple M2/M2D messages */
2005
2006 wpa_printf(MSG_DEBUG, "WPS: No more registrars available - "
2007 "terminate negotiation");
2008 }
2009
2010 return WPS_FAILURE;
2011}
2012
2013
2014static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps,
2015 const struct wpabuf *msg)
2016{
2017 struct wps_parse_attr attr;
469fc3a4 2018 int old_state;
ad08c363
JM
2019
2020 wpa_printf(MSG_DEBUG, "WPS: Received WSC_NACK");
2021
469fc3a4 2022 old_state = wps->state;
a92c421d
JM
2023 wps->state = SEND_WSC_NACK;
2024
ad08c363
JM
2025 if (wps_parse_msg(msg, &attr) < 0)
2026 return WPS_FAILURE;
2027
2028 if (attr.version == NULL || *attr.version != WPS_VERSION) {
2029 wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x",
2030 attr.version ? *attr.version : 0);
2031 return WPS_FAILURE;
2032 }
2033
2034 if (attr.msg_type == NULL) {
2035 wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
2036 return WPS_FAILURE;
2037 }
2038
2039 if (*attr.msg_type != WPS_WSC_NACK) {
2040 wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d",
2041 *attr.msg_type);
2042 return WPS_FAILURE;
2043 }
2044
2045 if (attr.registrar_nonce == NULL ||
2046 os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN != 0))
2047 {
2048 wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce");
2049 return WPS_FAILURE;
2050 }
2051
2052 if (attr.enrollee_nonce == NULL ||
2053 os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) {
2054 wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce");
2055 return WPS_FAILURE;
2056 }
2057
2058 if (attr.config_error == NULL) {
2059 wpa_printf(MSG_DEBUG, "WPS: No Configuration Error attribute "
2060 "in WSC_NACK");
2061 return WPS_FAILURE;
2062 }
2063
2064 wpa_printf(MSG_DEBUG, "WPS: Enrollee terminated negotiation with "
2065 "Configuration Error %d", WPA_GET_BE16(attr.config_error));
2066
469fc3a4
JM
2067 switch (old_state) {
2068 case RECV_M3:
2069 wps_fail_event(wps->wps, WPS_M2);
2070 break;
2071 case RECV_M5:
2072 wps_fail_event(wps->wps, WPS_M4);
2073 break;
2074 case RECV_M7:
2075 wps_fail_event(wps->wps, WPS_M6);
2076 break;
2077 case RECV_DONE:
2078 wps_fail_event(wps->wps, WPS_M8);
2079 break;
2080 default:
2081 break;
2082 }
2083
ad08c363
JM
2084 return WPS_FAILURE;
2085}
2086
2087
2088static enum wps_process_res wps_process_wsc_done(struct wps_data *wps,
2089 const struct wpabuf *msg)
2090{
2091 struct wps_parse_attr attr;
2092
2093 wpa_printf(MSG_DEBUG, "WPS: Received WSC_Done");
2094
2095 if (wps->state != RECV_DONE) {
2096 wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
2097 "receiving WSC_Done", wps->state);
2098 return WPS_FAILURE;
2099 }
2100
2101 if (wps_parse_msg(msg, &attr) < 0)
2102 return WPS_FAILURE;
2103
2104 if (attr.version == NULL || *attr.version != WPS_VERSION) {
2105 wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x",
2106 attr.version ? *attr.version : 0);
2107 return WPS_FAILURE;
2108 }
2109
2110 if (attr.msg_type == NULL) {
2111 wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
2112 return WPS_FAILURE;
2113 }
2114
2115 if (*attr.msg_type != WPS_WSC_DONE) {
2116 wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d",
2117 *attr.msg_type);
2118 return WPS_FAILURE;
2119 }
2120
2121 if (attr.registrar_nonce == NULL ||
2122 os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN != 0))
2123 {
2124 wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce");
2125 return WPS_FAILURE;
2126 }
2127
2128 if (attr.enrollee_nonce == NULL ||
2129 os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) {
2130 wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce");
2131 return WPS_FAILURE;
2132 }
2133
2134 wpa_printf(MSG_DEBUG, "WPS: Negotiation completed successfully");
2135
2136 if (wps->wps->wps_state == WPS_STATE_NOT_CONFIGURED && wps->new_psk &&
aabe26a1 2137 wps->wps->ap && !wps->wps->registrar->disable_auto_conf) {
ad08c363
JM
2138 struct wps_credential cred;
2139
2140 wpa_printf(MSG_DEBUG, "WPS: Moving to Configured state based "
2141 "on first Enrollee connection");
2142
2143 os_memset(&cred, 0, sizeof(cred));
2144 os_memcpy(cred.ssid, wps->wps->ssid, wps->wps->ssid_len);
2145 cred.ssid_len = wps->wps->ssid_len;
2146 cred.auth_type = WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK;
2147 cred.encr_type = WPS_ENCR_TKIP | WPS_ENCR_AES;
2148 os_memcpy(cred.key, wps->new_psk, wps->new_psk_len);
2149 cred.key_len = wps->new_psk_len;
2150
2151 wps->wps->wps_state = WPS_STATE_CONFIGURED;
2152 wpa_hexdump_ascii_key(MSG_DEBUG,
2153 "WPS: Generated random passphrase",
2154 wps->new_psk, wps->new_psk_len);
2155 if (wps->wps->cred_cb)
2156 wps->wps->cred_cb(wps->wps->cb_ctx, &cred);
2157
2158 os_free(wps->new_psk);
2159 wps->new_psk = NULL;
2160 }
2161
9d695f3d
JM
2162 if (!wps->wps->ap) {
2163 wpa_printf(MSG_DEBUG, "WPS: Update local configuration based "
2164 "on the modified AP configuration");
bcbbc7af
JM
2165 if (wps->wps->cred_cb)
2166 wps->wps->cred_cb(wps->wps->cb_ctx, &wps->cred);
9d695f3d
JM
2167 }
2168
ad08c363 2169 if (wps->new_psk) {
41c00105 2170 if (wps_cb_new_psk(wps->wps->registrar, wps->mac_addr_e,
ad08c363
JM
2171 wps->new_psk, wps->new_psk_len)) {
2172 wpa_printf(MSG_DEBUG, "WPS: Failed to configure the "
2173 "new PSK");
2174 }
2175 os_free(wps->new_psk);
2176 wps->new_psk = NULL;
2177 }
2178
aabe26a1
JM
2179 wps_cb_reg_success(wps->wps->registrar, wps->mac_addr_e, wps->uuid_e);
2180
ad08c363 2181 if (wps->pbc) {
41c00105 2182 wps_registrar_remove_pbc_session(wps->wps->registrar,
ad08c363 2183 wps->mac_addr_e, wps->uuid_e);
41c00105 2184 wps_registrar_pbc_completed(wps->wps->registrar);
ad08c363
JM
2185 }
2186
ad5302a1
JM
2187 wps_success_event(wps->wps);
2188
ad08c363
JM
2189 return WPS_DONE;
2190}
2191
2192
2193enum wps_process_res wps_registrar_process_msg(struct wps_data *wps,
f90c86d4 2194 enum wsc_op_code op_code,
ad08c363
JM
2195 const struct wpabuf *msg)
2196{
469fc3a4 2197 enum wps_process_res ret;
ad08c363
JM
2198
2199 wpa_printf(MSG_DEBUG, "WPS: Processing received message (len=%lu "
2200 "op_code=%d)",
2201 (unsigned long) wpabuf_len(msg), op_code);
2202
2203 switch (op_code) {
2204 case WSC_MSG:
2205 return wps_process_wsc_msg(wps, msg);
2206 case WSC_ACK:
2207 return wps_process_wsc_ack(wps, msg);
2208 case WSC_NACK:
2209 return wps_process_wsc_nack(wps, msg);
2210 case WSC_Done:
469fc3a4
JM
2211 ret = wps_process_wsc_done(wps, msg);
2212 if (ret == WPS_FAILURE) {
2213 wps->state = SEND_WSC_NACK;
2214 wps_fail_event(wps->wps, WPS_WSC_DONE);
2215 }
2216 return ret;
ad08c363
JM
2217 default:
2218 wpa_printf(MSG_DEBUG, "WPS: Unsupported op_code %d", op_code);
2219 return WPS_FAILURE;
2220 }
2221}