2 * Wi-Fi Protected Setup - Registrar
3 * Copyright (c) 2008-2009, Jouni Malinen <j@w1.fi>
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.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
15 #include "utils/includes.h"
17 #include "utils/common.h"
18 #include "utils/base64.h"
19 #include "utils/eloop.h"
20 #include "utils/uuid.h"
21 #include "utils/list.h"
22 #include "crypto/crypto.h"
23 #include "crypto/sha256.h"
24 #include "common/ieee802_11_defs.h"
26 #include "wps_dev_attr.h"
28 #include "wps_upnp_i.h"
30 #define WPS_WORKAROUNDS
34 u8 uuid
[WPS_UUID_LEN
];
38 #define PIN_LOCKED BIT(0)
39 #define PIN_EXPIRES BIT(1)
41 struct os_time expiration
;
45 static void wps_free_pin(struct wps_uuid_pin
*pin
)
52 static void wps_remove_pin(struct wps_uuid_pin
*pin
)
54 dl_list_del(&pin
->list
);
59 static void wps_free_pins(struct dl_list
*pins
)
61 struct wps_uuid_pin
*pin
, *prev
;
62 dl_list_for_each_safe(pin
, prev
, pins
, struct wps_uuid_pin
, list
)
67 struct wps_pbc_session
{
68 struct wps_pbc_session
*next
;
70 u8 uuid_e
[WPS_UUID_LEN
];
71 struct os_time timestamp
;
75 static void wps_free_pbc_sessions(struct wps_pbc_session
*pbc
)
77 struct wps_pbc_session
*prev
;
87 struct wps_registrar_device
{
88 struct wps_registrar_device
*next
;
89 struct wps_device_data dev
;
90 u8 uuid
[WPS_UUID_LEN
];
94 struct wps_registrar
{
95 struct wps_context
*wps
;
98 int selected_registrar
;
100 int (*new_psk_cb
)(void *ctx
, const u8
*mac_addr
, const u8
*psk
,
102 int (*set_ie_cb
)(void *ctx
, struct wpabuf
*beacon_ie
,
103 struct wpabuf
*probe_resp_ie
);
104 void (*pin_needed_cb
)(void *ctx
, const u8
*uuid_e
,
105 const struct wps_device_data
*dev
);
106 void (*reg_success_cb
)(void *ctx
, const u8
*mac_addr
,
108 void (*set_sel_reg_cb
)(void *ctx
, int sel_reg
, u16 dev_passwd_id
,
109 u16 sel_reg_config_methods
);
113 struct wps_pbc_session
*pbc_sessions
;
116 struct wpabuf
*extra_cred
;
117 int disable_auto_conf
;
119 int sel_reg_dev_password_id_override
;
120 int sel_reg_config_methods_override
;
123 struct wps_registrar_device
*devices
;
125 int force_pbc_overlap
;
129 static int wps_set_ie(struct wps_registrar
*reg
);
130 static void wps_registrar_pbc_timeout(void *eloop_ctx
, void *timeout_ctx
);
131 static void wps_registrar_set_selected_timeout(void *eloop_ctx
,
135 static void wps_free_devices(struct wps_registrar_device
*dev
)
137 struct wps_registrar_device
*prev
;
142 wps_device_data_free(&prev
->dev
);
148 static struct wps_registrar_device
* wps_device_get(struct wps_registrar
*reg
,
151 struct wps_registrar_device
*dev
;
153 for (dev
= reg
->devices
; dev
; dev
= dev
->next
) {
154 if (os_memcmp(dev
->dev
.mac_addr
, addr
, ETH_ALEN
) == 0)
161 static void wps_device_clone_data(struct wps_device_data
*dst
,
162 struct wps_device_data
*src
)
164 os_memcpy(dst
->mac_addr
, src
->mac_addr
, ETH_ALEN
);
165 os_memcpy(dst
->pri_dev_type
, src
->pri_dev_type
, WPS_DEV_TYPE_LEN
);
167 #define WPS_STRDUP(n) \
169 dst->n = src->n ? os_strdup(src->n) : NULL
171 WPS_STRDUP(device_name
);
172 WPS_STRDUP(manufacturer
);
173 WPS_STRDUP(model_name
);
174 WPS_STRDUP(model_number
);
175 WPS_STRDUP(serial_number
);
180 int wps_device_store(struct wps_registrar
*reg
,
181 struct wps_device_data
*dev
, const u8
*uuid
)
183 struct wps_registrar_device
*d
;
185 d
= wps_device_get(reg
, dev
->mac_addr
);
187 d
= os_zalloc(sizeof(*d
));
190 d
->next
= reg
->devices
;
194 wps_device_clone_data(&d
->dev
, dev
);
195 os_memcpy(d
->uuid
, uuid
, WPS_UUID_LEN
);
201 static void wps_registrar_add_pbc_session(struct wps_registrar
*reg
,
202 const u8
*addr
, const u8
*uuid_e
)
204 struct wps_pbc_session
*pbc
, *prev
= NULL
;
209 pbc
= reg
->pbc_sessions
;
211 if (os_memcmp(pbc
->addr
, addr
, ETH_ALEN
) == 0 &&
212 os_memcmp(pbc
->uuid_e
, uuid_e
, WPS_UUID_LEN
) == 0) {
214 prev
->next
= pbc
->next
;
216 reg
->pbc_sessions
= pbc
->next
;
224 pbc
= os_zalloc(sizeof(*pbc
));
227 os_memcpy(pbc
->addr
, addr
, ETH_ALEN
);
229 os_memcpy(pbc
->uuid_e
, uuid_e
, WPS_UUID_LEN
);
232 pbc
->next
= reg
->pbc_sessions
;
233 reg
->pbc_sessions
= pbc
;
234 pbc
->timestamp
= now
;
236 /* remove entries that have timed out */
241 if (now
.sec
> pbc
->timestamp
.sec
+ WPS_PBC_WALK_TIME
) {
243 wps_free_pbc_sessions(pbc
);
252 static void wps_registrar_remove_pbc_session(struct wps_registrar
*reg
,
253 const u8
*addr
, const u8
*uuid_e
)
255 struct wps_pbc_session
*pbc
, *prev
= NULL
;
257 pbc
= reg
->pbc_sessions
;
259 if (os_memcmp(pbc
->addr
, addr
, ETH_ALEN
) == 0 &&
260 os_memcmp(pbc
->uuid_e
, uuid_e
, WPS_UUID_LEN
) == 0) {
262 prev
->next
= pbc
->next
;
264 reg
->pbc_sessions
= pbc
->next
;
274 static int wps_registrar_pbc_overlap(struct wps_registrar
*reg
,
275 const u8
*addr
, const u8
*uuid_e
)
278 struct wps_pbc_session
*pbc
;
283 for (pbc
= reg
->pbc_sessions
; pbc
; pbc
= pbc
->next
) {
284 if (now
.sec
> pbc
->timestamp
.sec
+ WPS_PBC_WALK_TIME
)
286 if (addr
== NULL
|| os_memcmp(addr
, pbc
->addr
, ETH_ALEN
) ||
288 os_memcmp(uuid_e
, pbc
->uuid_e
, WPS_UUID_LEN
))
295 return count
> 1 ? 1 : 0;
299 static int wps_build_wps_state(struct wps_context
*wps
, struct wpabuf
*msg
)
301 wpa_printf(MSG_DEBUG
, "WPS: * Wi-Fi Protected Setup State (%d)",
303 wpabuf_put_be16(msg
, ATTR_WPS_STATE
);
304 wpabuf_put_be16(msg
, 1);
305 wpabuf_put_u8(msg
, wps
->wps_state
);
310 #ifdef CONFIG_WPS_UPNP
311 static void wps_registrar_free_pending_m2(struct wps_context
*wps
)
313 struct upnp_pending_message
*p
, *p2
, *prev
= NULL
;
316 if (p
->type
== WPS_M2
|| p
->type
== WPS_M2D
) {
318 wps
->upnp_msgs
= p
->next
;
320 prev
->next
= p
->next
;
321 wpa_printf(MSG_DEBUG
, "WPS UPnP: Drop pending M2/M2D");
324 wpabuf_free(p2
->msg
);
332 #endif /* CONFIG_WPS_UPNP */
335 static int wps_build_ap_setup_locked(struct wps_context
*wps
,
338 if (wps
->ap_setup_locked
) {
339 wpa_printf(MSG_DEBUG
, "WPS: * AP Setup Locked");
340 wpabuf_put_be16(msg
, ATTR_AP_SETUP_LOCKED
);
341 wpabuf_put_be16(msg
, 1);
342 wpabuf_put_u8(msg
, 1);
348 static int wps_build_selected_registrar(struct wps_registrar
*reg
,
351 if (!reg
->sel_reg_union
)
353 wpa_printf(MSG_DEBUG
, "WPS: * Selected Registrar");
354 wpabuf_put_be16(msg
, ATTR_SELECTED_REGISTRAR
);
355 wpabuf_put_be16(msg
, 1);
356 wpabuf_put_u8(msg
, 1);
361 static int wps_build_sel_reg_dev_password_id(struct wps_registrar
*reg
,
364 u16 id
= reg
->pbc
? DEV_PW_PUSHBUTTON
: DEV_PW_DEFAULT
;
365 if (!reg
->sel_reg_union
)
367 if (reg
->sel_reg_dev_password_id_override
>= 0)
368 id
= reg
->sel_reg_dev_password_id_override
;
369 wpa_printf(MSG_DEBUG
, "WPS: * Device Password ID (%d)", id
);
370 wpabuf_put_be16(msg
, ATTR_DEV_PASSWORD_ID
);
371 wpabuf_put_be16(msg
, 2);
372 wpabuf_put_be16(msg
, id
);
377 static int wps_build_sel_reg_config_methods(struct wps_registrar
*reg
,
381 if (!reg
->sel_reg_union
)
383 methods
= reg
->wps
->config_methods
& ~WPS_CONFIG_PUSHBUTTON
;
385 methods
|= WPS_CONFIG_PUSHBUTTON
;
386 if (reg
->sel_reg_config_methods_override
>= 0)
387 methods
= reg
->sel_reg_config_methods_override
;
388 wpa_printf(MSG_DEBUG
, "WPS: * Selected Registrar Config Methods (%x)",
390 wpabuf_put_be16(msg
, ATTR_SELECTED_REGISTRAR_CONFIG_METHODS
);
391 wpabuf_put_be16(msg
, 2);
392 wpabuf_put_be16(msg
, methods
);
397 static int wps_build_probe_config_methods(struct wps_registrar
*reg
,
402 wpa_printf(MSG_DEBUG
, "WPS: * Config Methods (%x)", methods
);
403 wpabuf_put_be16(msg
, ATTR_CONFIG_METHODS
);
404 wpabuf_put_be16(msg
, 2);
405 wpabuf_put_be16(msg
, methods
);
410 static int wps_build_config_methods_r(struct wps_registrar
*reg
,
414 methods
= reg
->wps
->config_methods
& ~WPS_CONFIG_PUSHBUTTON
;
416 methods
|= WPS_CONFIG_PUSHBUTTON
;
417 return wps_build_config_methods(msg
, methods
);
421 static int wps_build_resp_type(struct wps_registrar
*reg
, struct wpabuf
*msg
)
423 u8 resp
= reg
->wps
->ap
? WPS_RESP_AP
: WPS_RESP_REGISTRAR
;
424 wpa_printf(MSG_DEBUG
, "WPS: * Response Type (%d)", resp
);
425 wpabuf_put_be16(msg
, ATTR_RESPONSE_TYPE
);
426 wpabuf_put_be16(msg
, 1);
427 wpabuf_put_u8(msg
, resp
);
433 * wps_registrar_init - Initialize WPS Registrar data
434 * @wps: Pointer to longterm WPS context
435 * @cfg: Registrar configuration
436 * Returns: Pointer to allocated Registrar data or %NULL on failure
438 * This function is used to initialize WPS Registrar functionality. It can be
439 * used for a single Registrar run (e.g., when run in a supplicant) or multiple
440 * runs (e.g., when run as an internal Registrar in an AP). Caller is
441 * responsible for freeing the returned data with wps_registrar_deinit() when
442 * Registrar functionality is not needed anymore.
444 struct wps_registrar
*
445 wps_registrar_init(struct wps_context
*wps
,
446 const struct wps_registrar_config
*cfg
)
448 struct wps_registrar
*reg
= os_zalloc(sizeof(*reg
));
452 dl_list_init(®
->pins
);
454 reg
->new_psk_cb
= cfg
->new_psk_cb
;
455 reg
->set_ie_cb
= cfg
->set_ie_cb
;
456 reg
->pin_needed_cb
= cfg
->pin_needed_cb
;
457 reg
->reg_success_cb
= cfg
->reg_success_cb
;
458 reg
->set_sel_reg_cb
= cfg
->set_sel_reg_cb
;
459 reg
->cb_ctx
= cfg
->cb_ctx
;
460 reg
->skip_cred_build
= cfg
->skip_cred_build
;
461 if (cfg
->extra_cred
) {
462 reg
->extra_cred
= wpabuf_alloc_copy(cfg
->extra_cred
,
463 cfg
->extra_cred_len
);
464 if (reg
->extra_cred
== NULL
) {
469 reg
->disable_auto_conf
= cfg
->disable_auto_conf
;
470 reg
->sel_reg_dev_password_id_override
= -1;
471 reg
->sel_reg_config_methods_override
= -1;
472 reg
->static_wep_only
= cfg
->static_wep_only
;
474 if (wps_set_ie(reg
)) {
475 wps_registrar_deinit(reg
);
484 * wps_registrar_deinit - Deinitialize WPS Registrar data
485 * @reg: Registrar data from wps_registrar_init()
487 void wps_registrar_deinit(struct wps_registrar
*reg
)
491 eloop_cancel_timeout(wps_registrar_pbc_timeout
, reg
, NULL
);
492 eloop_cancel_timeout(wps_registrar_set_selected_timeout
, reg
, NULL
);
493 wps_free_pins(®
->pins
);
494 wps_free_pbc_sessions(reg
->pbc_sessions
);
495 wpabuf_free(reg
->extra_cred
);
496 wps_free_devices(reg
->devices
);
502 * wps_registrar_add_pin - Configure a new PIN for Registrar
503 * @reg: Registrar data from wps_registrar_init()
504 * @uuid: UUID-E or %NULL for wildcard (any UUID)
505 * @pin: PIN (Device Password)
506 * @pin_len: Length of pin in octets
507 * @timeout: Time (in seconds) when the PIN will be invalidated; 0 = no timeout
508 * Returns: 0 on success, -1 on failure
510 int wps_registrar_add_pin(struct wps_registrar
*reg
, const u8
*uuid
,
511 const u8
*pin
, size_t pin_len
, int timeout
)
513 struct wps_uuid_pin
*p
;
515 p
= os_zalloc(sizeof(*p
));
519 p
->wildcard_uuid
= 1;
521 os_memcpy(p
->uuid
, uuid
, WPS_UUID_LEN
);
522 p
->pin
= os_malloc(pin_len
);
523 if (p
->pin
== NULL
) {
527 os_memcpy(p
->pin
, pin
, pin_len
);
528 p
->pin_len
= pin_len
;
531 p
->flags
|= PIN_EXPIRES
;
532 os_get_time(&p
->expiration
);
533 p
->expiration
.sec
+= timeout
;
536 dl_list_add(®
->pins
, &p
->list
);
538 wpa_printf(MSG_DEBUG
, "WPS: A new PIN configured (timeout=%d)",
540 wpa_hexdump(MSG_DEBUG
, "WPS: UUID", uuid
, WPS_UUID_LEN
);
541 wpa_hexdump_ascii_key(MSG_DEBUG
, "WPS: PIN", pin
, pin_len
);
542 reg
->selected_registrar
= 1;
544 wps_registrar_selected_registrar_changed(reg
);
545 eloop_cancel_timeout(wps_registrar_set_selected_timeout
, reg
, NULL
);
546 eloop_register_timeout(WPS_PBC_WALK_TIME
, 0,
547 wps_registrar_set_selected_timeout
,
554 static void wps_registrar_expire_pins(struct wps_registrar
*reg
)
556 struct wps_uuid_pin
*pin
, *prev
;
560 dl_list_for_each_safe(pin
, prev
, ®
->pins
, struct wps_uuid_pin
, list
)
562 if ((pin
->flags
& PIN_EXPIRES
) &&
563 os_time_before(&pin
->expiration
, &now
)) {
564 wpa_hexdump(MSG_DEBUG
, "WPS: Expired PIN for UUID",
565 pin
->uuid
, WPS_UUID_LEN
);
573 * wps_registrar_invalidate_pin - Invalidate a PIN for a specific UUID-E
574 * @reg: Registrar data from wps_registrar_init()
576 * Returns: 0 on success, -1 on failure (e.g., PIN not found)
578 int wps_registrar_invalidate_pin(struct wps_registrar
*reg
, const u8
*uuid
)
580 struct wps_uuid_pin
*pin
, *prev
;
582 dl_list_for_each_safe(pin
, prev
, ®
->pins
, struct wps_uuid_pin
, list
)
584 if (os_memcmp(pin
->uuid
, uuid
, WPS_UUID_LEN
) == 0) {
585 wpa_hexdump(MSG_DEBUG
, "WPS: Invalidated PIN for UUID",
586 pin
->uuid
, WPS_UUID_LEN
);
596 static const u8
* wps_registrar_get_pin(struct wps_registrar
*reg
,
597 const u8
*uuid
, size_t *pin_len
)
599 struct wps_uuid_pin
*pin
, *found
= NULL
;
601 wps_registrar_expire_pins(reg
);
603 dl_list_for_each(pin
, ®
->pins
, struct wps_uuid_pin
, list
) {
604 if (!pin
->wildcard_uuid
&&
605 os_memcmp(pin
->uuid
, uuid
, WPS_UUID_LEN
) == 0) {
612 /* Check for wildcard UUIDs since none of the UUID-specific
614 dl_list_for_each(pin
, ®
->pins
, struct wps_uuid_pin
, list
) {
615 if (pin
->wildcard_uuid
== 1) {
616 wpa_printf(MSG_DEBUG
, "WPS: Found a wildcard "
617 "PIN. Assigned it for this UUID-E");
618 pin
->wildcard_uuid
= 2;
619 os_memcpy(pin
->uuid
, uuid
, WPS_UUID_LEN
);
630 * Lock the PIN to avoid attacks based on concurrent re-use of the PIN
631 * that could otherwise avoid PIN invalidations.
633 if (found
->flags
& PIN_LOCKED
) {
634 wpa_printf(MSG_DEBUG
, "WPS: Selected PIN locked - do not "
635 "allow concurrent re-use");
638 *pin_len
= found
->pin_len
;
639 found
->flags
|= PIN_LOCKED
;
645 * wps_registrar_unlock_pin - Unlock a PIN for a specific UUID-E
646 * @reg: Registrar data from wps_registrar_init()
648 * Returns: 0 on success, -1 on failure
650 * PINs are locked to enforce only one concurrent use. This function unlocks a
651 * PIN to allow it to be used again. If the specified PIN was configured using
652 * a wildcard UUID, it will be removed instead of allowing multiple uses.
654 int wps_registrar_unlock_pin(struct wps_registrar
*reg
, const u8
*uuid
)
656 struct wps_uuid_pin
*pin
;
658 dl_list_for_each(pin
, ®
->pins
, struct wps_uuid_pin
, list
) {
659 if (os_memcmp(pin
->uuid
, uuid
, WPS_UUID_LEN
) == 0) {
660 if (pin
->wildcard_uuid
== 2) {
661 wpa_printf(MSG_DEBUG
, "WPS: Invalidating used "
663 return wps_registrar_invalidate_pin(reg
, uuid
);
665 pin
->flags
&= ~PIN_LOCKED
;
674 static void wps_registrar_stop_pbc(struct wps_registrar
*reg
)
676 reg
->selected_registrar
= 0;
678 wps_registrar_selected_registrar_changed(reg
);
682 static void wps_registrar_pbc_timeout(void *eloop_ctx
, void *timeout_ctx
)
684 struct wps_registrar
*reg
= eloop_ctx
;
686 wpa_printf(MSG_DEBUG
, "WPS: PBC timed out - disable PBC mode");
687 wps_pbc_timeout_event(reg
->wps
);
688 wps_registrar_stop_pbc(reg
);
693 * wps_registrar_button_pushed - Notify Registrar that AP button was pushed
694 * @reg: Registrar data from wps_registrar_init()
695 * Returns: 0 on success, -1 on failure
697 * This function is called on an AP when a push button is pushed to activate
698 * PBC mode. The PBC mode will be stopped after walk time (2 minutes) timeout
699 * or when a PBC registration is completed.
701 int wps_registrar_button_pushed(struct wps_registrar
*reg
)
703 if (wps_registrar_pbc_overlap(reg
, NULL
, NULL
)) {
704 wpa_printf(MSG_DEBUG
, "WPS: PBC overlap - do not start PBC "
706 wps_pbc_overlap_event(reg
->wps
);
709 wpa_printf(MSG_DEBUG
, "WPS: Button pushed - PBC mode started");
710 reg
->force_pbc_overlap
= 0;
711 reg
->selected_registrar
= 1;
713 wps_registrar_selected_registrar_changed(reg
);
715 eloop_cancel_timeout(wps_registrar_pbc_timeout
, reg
, NULL
);
716 eloop_register_timeout(WPS_PBC_WALK_TIME
, 0, wps_registrar_pbc_timeout
,
722 static void wps_registrar_pbc_completed(struct wps_registrar
*reg
)
724 wpa_printf(MSG_DEBUG
, "WPS: PBC completed - stopping PBC mode");
725 eloop_cancel_timeout(wps_registrar_pbc_timeout
, reg
, NULL
);
726 wps_registrar_stop_pbc(reg
);
730 static void wps_registrar_pin_completed(struct wps_registrar
*reg
)
732 wpa_printf(MSG_DEBUG
, "WPS: PIN completed using internal Registrar");
733 eloop_cancel_timeout(wps_registrar_set_selected_timeout
, reg
, NULL
);
734 reg
->selected_registrar
= 0;
735 wps_registrar_selected_registrar_changed(reg
);
740 * wps_registrar_probe_req_rx - Notify Registrar of Probe Request
741 * @reg: Registrar data from wps_registrar_init()
742 * @addr: MAC address of the Probe Request sender
743 * @wps_data: WPS IE contents
745 * This function is called on an AP when a Probe Request with WPS IE is
746 * received. This is used to track PBC mode use and to detect possible overlap
747 * situation with other WPS APs.
749 void wps_registrar_probe_req_rx(struct wps_registrar
*reg
, const u8
*addr
,
750 const struct wpabuf
*wps_data
)
752 struct wps_parse_attr attr
;
755 wpa_hexdump_buf(MSG_MSGDUMP
,
756 "WPS: Probe Request with WPS data received",
759 if (wps_parse_msg(wps_data
, &attr
) < 0)
761 if (!wps_version_supported(attr
.version
)) {
762 wpa_printf(MSG_DEBUG
, "WPS: Unsupported ProbeReq WPS IE "
763 "version 0x%x", attr
.version
? *attr
.version
: 0);
767 if (attr
.config_methods
== NULL
) {
768 wpa_printf(MSG_DEBUG
, "WPS: No Config Methods attribute in "
773 methods
= WPA_GET_BE16(attr
.config_methods
);
774 if (!(methods
& WPS_CONFIG_PUSHBUTTON
))
775 return; /* Not PBC */
777 wpa_printf(MSG_DEBUG
, "WPS: Probe Request for PBC received from "
778 MACSTR
, MAC2STR(addr
));
780 wps_registrar_add_pbc_session(reg
, addr
, attr
.uuid_e
);
781 if (wps_registrar_pbc_overlap(reg
, addr
, attr
.uuid_e
)) {
782 wpa_printf(MSG_DEBUG
, "WPS: PBC session overlap detected");
783 reg
->force_pbc_overlap
= 1;
784 wps_pbc_overlap_event(reg
->wps
);
789 static int wps_cb_new_psk(struct wps_registrar
*reg
, const u8
*mac_addr
,
790 const u8
*psk
, size_t psk_len
)
792 if (reg
->new_psk_cb
== NULL
)
795 return reg
->new_psk_cb(reg
->cb_ctx
, mac_addr
, psk
, psk_len
);
799 static void wps_cb_pin_needed(struct wps_registrar
*reg
, const u8
*uuid_e
,
800 const struct wps_device_data
*dev
)
802 if (reg
->pin_needed_cb
== NULL
)
805 reg
->pin_needed_cb(reg
->cb_ctx
, uuid_e
, dev
);
809 static void wps_cb_reg_success(struct wps_registrar
*reg
, const u8
*mac_addr
,
812 if (reg
->reg_success_cb
== NULL
)
815 reg
->reg_success_cb(reg
->cb_ctx
, mac_addr
, uuid_e
);
819 static int wps_cb_set_ie(struct wps_registrar
*reg
, struct wpabuf
*beacon_ie
,
820 struct wpabuf
*probe_resp_ie
)
822 return reg
->set_ie_cb(reg
->cb_ctx
, beacon_ie
, probe_resp_ie
);
826 static void wps_cb_set_sel_reg(struct wps_registrar
*reg
)
829 if (reg
->set_sel_reg_cb
== NULL
)
832 if (reg
->selected_registrar
) {
833 methods
= reg
->wps
->config_methods
& ~WPS_CONFIG_PUSHBUTTON
;
835 methods
|= WPS_CONFIG_PUSHBUTTON
;
838 reg
->set_sel_reg_cb(reg
->cb_ctx
, reg
->selected_registrar
,
839 reg
->pbc
? DEV_PW_PUSHBUTTON
: DEV_PW_DEFAULT
,
844 /* Encapsulate WPS IE data with one (or more, if needed) IE headers */
845 static struct wpabuf
* wps_ie_encapsulate(struct wpabuf
*data
)
850 ie
= wpabuf_alloc(wpabuf_len(data
) + 100);
856 pos
= wpabuf_head(data
);
857 end
= pos
+ wpabuf_len(data
);
860 size_t frag_len
= end
- pos
;
863 wpabuf_put_u8(ie
, WLAN_EID_VENDOR_SPECIFIC
);
864 wpabuf_put_u8(ie
, 4 + frag_len
);
865 wpabuf_put_be32(ie
, WPS_DEV_OUI_WFA
);
866 wpabuf_put_data(ie
, pos
, frag_len
);
876 static int wps_set_ie(struct wps_registrar
*reg
)
878 struct wpabuf
*beacon
;
879 struct wpabuf
*probe
;
881 if (reg
->set_ie_cb
== NULL
)
884 wpa_printf(MSG_DEBUG
, "WPS: Build Beacon and Probe Response IEs");
886 beacon
= wpabuf_alloc(300);
889 probe
= wpabuf_alloc(400);
895 if (wps_build_version(beacon
) ||
896 wps_build_wps_state(reg
->wps
, beacon
) ||
897 wps_build_ap_setup_locked(reg
->wps
, beacon
) ||
898 wps_build_selected_registrar(reg
, beacon
) ||
899 wps_build_sel_reg_dev_password_id(reg
, beacon
) ||
900 wps_build_sel_reg_config_methods(reg
, beacon
) ||
901 wps_build_version(probe
) ||
902 wps_build_wps_state(reg
->wps
, probe
) ||
903 wps_build_ap_setup_locked(reg
->wps
, probe
) ||
904 wps_build_selected_registrar(reg
, probe
) ||
905 wps_build_sel_reg_dev_password_id(reg
, probe
) ||
906 wps_build_sel_reg_config_methods(reg
, probe
) ||
907 wps_build_resp_type(reg
, probe
) ||
908 wps_build_uuid_e(probe
, reg
->wps
->uuid
) ||
909 wps_build_device_attrs(®
->wps
->dev
, probe
) ||
910 wps_build_probe_config_methods(reg
, probe
) ||
911 wps_build_rf_bands(®
->wps
->dev
, probe
)) {
917 beacon
= wps_ie_encapsulate(beacon
);
918 probe
= wps_ie_encapsulate(probe
);
920 if (!beacon
|| !probe
) {
926 if (reg
->static_wep_only
) {
928 * Windows XP and Vista clients can get confused about
929 * EAP-Identity/Request when they probe the network with
930 * EAPOL-Start. In such a case, they may assume the network is
931 * using IEEE 802.1X and prompt user for a certificate while
932 * the correct (non-WPS) behavior would be to ask for the
933 * static WEP key. As a workaround, use Microsoft Provisioning
934 * IE to advertise that legacy 802.1X is not supported.
936 const u8 ms_wps
[7] = {
937 WLAN_EID_VENDOR_SPECIFIC
, 5,
938 /* Microsoft Provisioning IE (00:50:f2:5) */
940 0x00 /* no legacy 802.1X or MS WPS */
942 wpa_printf(MSG_DEBUG
, "WPS: Add Microsoft Provisioning IE "
943 "into Beacon/Probe Response frames");
944 wpabuf_put_data(beacon
, ms_wps
, sizeof(ms_wps
));
945 wpabuf_put_data(probe
, ms_wps
, sizeof(ms_wps
));
948 return wps_cb_set_ie(reg
, beacon
, probe
);
952 static int wps_get_dev_password(struct wps_data
*wps
)
957 os_free(wps
->dev_password
);
958 wps
->dev_password
= NULL
;
961 wpa_printf(MSG_DEBUG
, "WPS: Use default PIN for PBC");
962 pin
= (const u8
*) "00000000";
965 pin
= wps_registrar_get_pin(wps
->wps
->registrar
, wps
->uuid_e
,
969 wpa_printf(MSG_DEBUG
, "WPS: No Device Password available for "
971 wps_cb_pin_needed(wps
->wps
->registrar
, wps
->uuid_e
,
976 wps
->dev_password
= os_malloc(pin_len
);
977 if (wps
->dev_password
== NULL
)
979 os_memcpy(wps
->dev_password
, pin
, pin_len
);
980 wps
->dev_password_len
= pin_len
;
986 static int wps_build_uuid_r(struct wps_data
*wps
, struct wpabuf
*msg
)
988 wpa_printf(MSG_DEBUG
, "WPS: * UUID-R");
989 wpabuf_put_be16(msg
, ATTR_UUID_R
);
990 wpabuf_put_be16(msg
, WPS_UUID_LEN
);
991 wpabuf_put_data(msg
, wps
->uuid_r
, WPS_UUID_LEN
);
996 static int wps_build_r_hash(struct wps_data
*wps
, struct wpabuf
*msg
)
1002 if (os_get_random(wps
->snonce
, 2 * WPS_SECRET_NONCE_LEN
) < 0)
1004 wpa_hexdump(MSG_DEBUG
, "WPS: R-S1", wps
->snonce
, WPS_SECRET_NONCE_LEN
);
1005 wpa_hexdump(MSG_DEBUG
, "WPS: R-S2",
1006 wps
->snonce
+ WPS_SECRET_NONCE_LEN
, WPS_SECRET_NONCE_LEN
);
1008 if (wps
->dh_pubkey_e
== NULL
|| wps
->dh_pubkey_r
== NULL
) {
1009 wpa_printf(MSG_DEBUG
, "WPS: DH public keys not available for "
1010 "R-Hash derivation");
1014 wpa_printf(MSG_DEBUG
, "WPS: * R-Hash1");
1015 wpabuf_put_be16(msg
, ATTR_R_HASH1
);
1016 wpabuf_put_be16(msg
, SHA256_MAC_LEN
);
1017 hash
= wpabuf_put(msg
, SHA256_MAC_LEN
);
1018 /* R-Hash1 = HMAC_AuthKey(R-S1 || PSK1 || PK_E || PK_R) */
1019 addr
[0] = wps
->snonce
;
1020 len
[0] = WPS_SECRET_NONCE_LEN
;
1021 addr
[1] = wps
->psk1
;
1022 len
[1] = WPS_PSK_LEN
;
1023 addr
[2] = wpabuf_head(wps
->dh_pubkey_e
);
1024 len
[2] = wpabuf_len(wps
->dh_pubkey_e
);
1025 addr
[3] = wpabuf_head(wps
->dh_pubkey_r
);
1026 len
[3] = wpabuf_len(wps
->dh_pubkey_r
);
1027 hmac_sha256_vector(wps
->authkey
, WPS_AUTHKEY_LEN
, 4, addr
, len
, hash
);
1028 wpa_hexdump(MSG_DEBUG
, "WPS: R-Hash1", hash
, SHA256_MAC_LEN
);
1030 wpa_printf(MSG_DEBUG
, "WPS: * R-Hash2");
1031 wpabuf_put_be16(msg
, ATTR_R_HASH2
);
1032 wpabuf_put_be16(msg
, SHA256_MAC_LEN
);
1033 hash
= wpabuf_put(msg
, SHA256_MAC_LEN
);
1034 /* R-Hash2 = HMAC_AuthKey(R-S2 || PSK2 || PK_E || PK_R) */
1035 addr
[0] = wps
->snonce
+ WPS_SECRET_NONCE_LEN
;
1036 addr
[1] = wps
->psk2
;
1037 hmac_sha256_vector(wps
->authkey
, WPS_AUTHKEY_LEN
, 4, addr
, len
, hash
);
1038 wpa_hexdump(MSG_DEBUG
, "WPS: R-Hash2", hash
, SHA256_MAC_LEN
);
1044 static int wps_build_r_snonce1(struct wps_data
*wps
, struct wpabuf
*msg
)
1046 wpa_printf(MSG_DEBUG
, "WPS: * R-SNonce1");
1047 wpabuf_put_be16(msg
, ATTR_R_SNONCE1
);
1048 wpabuf_put_be16(msg
, WPS_SECRET_NONCE_LEN
);
1049 wpabuf_put_data(msg
, wps
->snonce
, WPS_SECRET_NONCE_LEN
);
1054 static int wps_build_r_snonce2(struct wps_data
*wps
, struct wpabuf
*msg
)
1056 wpa_printf(MSG_DEBUG
, "WPS: * R-SNonce2");
1057 wpabuf_put_be16(msg
, ATTR_R_SNONCE2
);
1058 wpabuf_put_be16(msg
, WPS_SECRET_NONCE_LEN
);
1059 wpabuf_put_data(msg
, wps
->snonce
+ WPS_SECRET_NONCE_LEN
,
1060 WPS_SECRET_NONCE_LEN
);
1065 static int wps_build_cred_network_idx(struct wpabuf
*msg
,
1066 const struct wps_credential
*cred
)
1068 wpa_printf(MSG_DEBUG
, "WPS: * Network Index");
1069 wpabuf_put_be16(msg
, ATTR_NETWORK_INDEX
);
1070 wpabuf_put_be16(msg
, 1);
1071 wpabuf_put_u8(msg
, 1);
1076 static int wps_build_cred_ssid(struct wpabuf
*msg
,
1077 const struct wps_credential
*cred
)
1079 wpa_printf(MSG_DEBUG
, "WPS: * SSID");
1080 wpabuf_put_be16(msg
, ATTR_SSID
);
1081 wpabuf_put_be16(msg
, cred
->ssid_len
);
1082 wpabuf_put_data(msg
, cred
->ssid
, cred
->ssid_len
);
1087 static int wps_build_cred_auth_type(struct wpabuf
*msg
,
1088 const struct wps_credential
*cred
)
1090 wpa_printf(MSG_DEBUG
, "WPS: * Authentication Type (0x%x)",
1092 wpabuf_put_be16(msg
, ATTR_AUTH_TYPE
);
1093 wpabuf_put_be16(msg
, 2);
1094 wpabuf_put_be16(msg
, cred
->auth_type
);
1099 static int wps_build_cred_encr_type(struct wpabuf
*msg
,
1100 const struct wps_credential
*cred
)
1102 wpa_printf(MSG_DEBUG
, "WPS: * Encryption Type (0x%x)",
1104 wpabuf_put_be16(msg
, ATTR_ENCR_TYPE
);
1105 wpabuf_put_be16(msg
, 2);
1106 wpabuf_put_be16(msg
, cred
->encr_type
);
1111 static int wps_build_cred_network_key(struct wpabuf
*msg
,
1112 const struct wps_credential
*cred
)
1114 wpa_printf(MSG_DEBUG
, "WPS: * Network Key (len=%d)",
1115 (int) cred
->key_len
);
1116 wpabuf_put_be16(msg
, ATTR_NETWORK_KEY
);
1117 wpabuf_put_be16(msg
, cred
->key_len
);
1118 wpabuf_put_data(msg
, cred
->key
, cred
->key_len
);
1123 static int wps_build_cred_mac_addr(struct wpabuf
*msg
,
1124 const struct wps_credential
*cred
)
1126 wpa_printf(MSG_DEBUG
, "WPS: * MAC Address (" MACSTR
")",
1127 MAC2STR(cred
->mac_addr
));
1128 wpabuf_put_be16(msg
, ATTR_MAC_ADDR
);
1129 wpabuf_put_be16(msg
, ETH_ALEN
);
1130 wpabuf_put_data(msg
, cred
->mac_addr
, ETH_ALEN
);
1135 static int wps_build_credential(struct wpabuf
*msg
,
1136 const struct wps_credential
*cred
)
1138 if (wps_build_cred_network_idx(msg
, cred
) ||
1139 wps_build_cred_ssid(msg
, cred
) ||
1140 wps_build_cred_auth_type(msg
, cred
) ||
1141 wps_build_cred_encr_type(msg
, cred
) ||
1142 wps_build_cred_network_key(msg
, cred
) ||
1143 wps_build_cred_mac_addr(msg
, cred
))
1149 int wps_build_cred(struct wps_data
*wps
, struct wpabuf
*msg
)
1151 struct wpabuf
*cred
;
1153 if (wps
->wps
->registrar
->skip_cred_build
)
1154 goto skip_cred_build
;
1156 wpa_printf(MSG_DEBUG
, "WPS: * Credential");
1157 if (wps
->use_cred
) {
1158 os_memcpy(&wps
->cred
, wps
->use_cred
, sizeof(wps
->cred
));
1161 os_memset(&wps
->cred
, 0, sizeof(wps
->cred
));
1163 os_memcpy(wps
->cred
.ssid
, wps
->wps
->ssid
, wps
->wps
->ssid_len
);
1164 wps
->cred
.ssid_len
= wps
->wps
->ssid_len
;
1166 /* Select the best authentication and encryption type */
1167 if (wps
->auth_type
& WPS_AUTH_WPA2PSK
)
1168 wps
->auth_type
= WPS_AUTH_WPA2PSK
;
1169 else if (wps
->auth_type
& WPS_AUTH_WPAPSK
)
1170 wps
->auth_type
= WPS_AUTH_WPAPSK
;
1171 else if (wps
->auth_type
& WPS_AUTH_OPEN
)
1172 wps
->auth_type
= WPS_AUTH_OPEN
;
1173 else if (wps
->auth_type
& WPS_AUTH_SHARED
)
1174 wps
->auth_type
= WPS_AUTH_SHARED
;
1176 wpa_printf(MSG_DEBUG
, "WPS: Unsupported auth_type 0x%x",
1180 wps
->cred
.auth_type
= wps
->auth_type
;
1182 if (wps
->auth_type
== WPS_AUTH_WPA2PSK
||
1183 wps
->auth_type
== WPS_AUTH_WPAPSK
) {
1184 if (wps
->encr_type
& WPS_ENCR_AES
)
1185 wps
->encr_type
= WPS_ENCR_AES
;
1186 else if (wps
->encr_type
& WPS_ENCR_TKIP
)
1187 wps
->encr_type
= WPS_ENCR_TKIP
;
1189 wpa_printf(MSG_DEBUG
, "WPS: No suitable encryption "
1190 "type for WPA/WPA2");
1194 if (wps
->encr_type
& WPS_ENCR_WEP
)
1195 wps
->encr_type
= WPS_ENCR_WEP
;
1196 else if (wps
->encr_type
& WPS_ENCR_NONE
)
1197 wps
->encr_type
= WPS_ENCR_NONE
;
1199 wpa_printf(MSG_DEBUG
, "WPS: No suitable encryption "
1200 "type for non-WPA/WPA2 mode");
1204 wps
->cred
.encr_type
= wps
->encr_type
;
1206 * Set MAC address in the Credential to be the Enrollee's MAC address
1208 os_memcpy(wps
->cred
.mac_addr
, wps
->mac_addr_e
, ETH_ALEN
);
1210 if (wps
->wps
->wps_state
== WPS_STATE_NOT_CONFIGURED
&& wps
->wps
->ap
&&
1211 !wps
->wps
->registrar
->disable_auto_conf
) {
1213 /* Generate a random passphrase */
1214 if (os_get_random(r
, sizeof(r
)) < 0)
1216 os_free(wps
->new_psk
);
1217 wps
->new_psk
= base64_encode(r
, sizeof(r
), &wps
->new_psk_len
);
1218 if (wps
->new_psk
== NULL
)
1220 wps
->new_psk_len
--; /* remove newline */
1221 while (wps
->new_psk_len
&&
1222 wps
->new_psk
[wps
->new_psk_len
- 1] == '=')
1224 wpa_hexdump_ascii_key(MSG_DEBUG
, "WPS: Generated passphrase",
1225 wps
->new_psk
, wps
->new_psk_len
);
1226 os_memcpy(wps
->cred
.key
, wps
->new_psk
, wps
->new_psk_len
);
1227 wps
->cred
.key_len
= wps
->new_psk_len
;
1228 } else if (wps
->use_psk_key
&& wps
->wps
->psk_set
) {
1230 wpa_printf(MSG_DEBUG
, "WPS: Use PSK format for Network Key");
1231 wpa_snprintf_hex(hex
, sizeof(hex
), wps
->wps
->psk
, 32);
1232 os_memcpy(wps
->cred
.key
, hex
, 32 * 2);
1233 wps
->cred
.key_len
= 32 * 2;
1234 } else if (wps
->wps
->network_key
) {
1235 os_memcpy(wps
->cred
.key
, wps
->wps
->network_key
,
1236 wps
->wps
->network_key_len
);
1237 wps
->cred
.key_len
= wps
->wps
->network_key_len
;
1238 } else if (wps
->auth_type
& (WPS_AUTH_WPAPSK
| WPS_AUTH_WPA2PSK
)) {
1240 /* Generate a random per-device PSK */
1241 os_free(wps
->new_psk
);
1242 wps
->new_psk_len
= 32;
1243 wps
->new_psk
= os_malloc(wps
->new_psk_len
);
1244 if (wps
->new_psk
== NULL
)
1246 if (os_get_random(wps
->new_psk
, wps
->new_psk_len
) < 0) {
1247 os_free(wps
->new_psk
);
1248 wps
->new_psk
= NULL
;
1251 wpa_hexdump_key(MSG_DEBUG
, "WPS: Generated per-device PSK",
1252 wps
->new_psk
, wps
->new_psk_len
);
1253 wpa_snprintf_hex(hex
, sizeof(hex
), wps
->new_psk
,
1255 os_memcpy(wps
->cred
.key
, hex
, wps
->new_psk_len
* 2);
1256 wps
->cred
.key_len
= wps
->new_psk_len
* 2;
1260 cred
= wpabuf_alloc(200);
1264 if (wps_build_credential(cred
, &wps
->cred
)) {
1269 wpabuf_put_be16(msg
, ATTR_CRED
);
1270 wpabuf_put_be16(msg
, wpabuf_len(cred
));
1271 wpabuf_put_buf(msg
, cred
);
1275 if (wps
->wps
->registrar
->extra_cred
) {
1276 wpa_printf(MSG_DEBUG
, "WPS: * Credential (pre-configured)");
1277 wpabuf_put_buf(msg
, wps
->wps
->registrar
->extra_cred
);
1284 static int wps_build_ap_settings(struct wps_data
*wps
, struct wpabuf
*msg
)
1286 wpa_printf(MSG_DEBUG
, "WPS: * AP Settings");
1288 if (wps_build_credential(msg
, &wps
->cred
))
1295 static struct wpabuf
* wps_build_m2(struct wps_data
*wps
)
1299 if (os_get_random(wps
->nonce_r
, WPS_NONCE_LEN
) < 0)
1301 wpa_hexdump(MSG_DEBUG
, "WPS: Registrar Nonce",
1302 wps
->nonce_r
, WPS_NONCE_LEN
);
1303 wpa_hexdump(MSG_DEBUG
, "WPS: UUID-R", wps
->uuid_r
, WPS_UUID_LEN
);
1305 wpa_printf(MSG_DEBUG
, "WPS: Building Message M2");
1306 msg
= wpabuf_alloc(1000);
1310 if (wps_build_version(msg
) ||
1311 wps_build_msg_type(msg
, WPS_M2
) ||
1312 wps_build_enrollee_nonce(wps
, msg
) ||
1313 wps_build_registrar_nonce(wps
, msg
) ||
1314 wps_build_uuid_r(wps
, msg
) ||
1315 wps_build_public_key(wps
, msg
) ||
1316 wps_derive_keys(wps
) ||
1317 wps_build_auth_type_flags(wps
, msg
) ||
1318 wps_build_encr_type_flags(wps
, msg
) ||
1319 wps_build_conn_type_flags(wps
, msg
) ||
1320 wps_build_config_methods_r(wps
->wps
->registrar
, msg
) ||
1321 wps_build_device_attrs(&wps
->wps
->dev
, msg
) ||
1322 wps_build_rf_bands(&wps
->wps
->dev
, msg
) ||
1323 wps_build_assoc_state(wps
, msg
) ||
1324 wps_build_config_error(msg
, WPS_CFG_NO_ERROR
) ||
1325 wps_build_dev_password_id(msg
, wps
->dev_pw_id
) ||
1326 wps_build_os_version(&wps
->wps
->dev
, msg
) ||
1327 wps_build_authenticator(wps
, msg
)) {
1332 wps
->state
= RECV_M3
;
1337 static struct wpabuf
* wps_build_m2d(struct wps_data
*wps
)
1340 u16 err
= wps
->config_error
;
1342 wpa_printf(MSG_DEBUG
, "WPS: Building Message M2D");
1343 msg
= wpabuf_alloc(1000);
1347 if (wps
->wps
->ap
&& wps
->wps
->ap_setup_locked
&&
1348 err
== WPS_CFG_NO_ERROR
)
1349 err
= WPS_CFG_SETUP_LOCKED
;
1351 if (wps_build_version(msg
) ||
1352 wps_build_msg_type(msg
, WPS_M2D
) ||
1353 wps_build_enrollee_nonce(wps
, msg
) ||
1354 wps_build_registrar_nonce(wps
, msg
) ||
1355 wps_build_uuid_r(wps
, msg
) ||
1356 wps_build_auth_type_flags(wps
, msg
) ||
1357 wps_build_encr_type_flags(wps
, msg
) ||
1358 wps_build_conn_type_flags(wps
, msg
) ||
1359 wps_build_config_methods_r(wps
->wps
->registrar
, msg
) ||
1360 wps_build_device_attrs(&wps
->wps
->dev
, msg
) ||
1361 wps_build_rf_bands(&wps
->wps
->dev
, msg
) ||
1362 wps_build_assoc_state(wps
, msg
) ||
1363 wps_build_config_error(msg
, err
) ||
1364 wps_build_os_version(&wps
->wps
->dev
, msg
)) {
1369 wps
->state
= RECV_M2D_ACK
;
1374 static struct wpabuf
* wps_build_m4(struct wps_data
*wps
)
1376 struct wpabuf
*msg
, *plain
;
1378 wpa_printf(MSG_DEBUG
, "WPS: Building Message M4");
1380 wps_derive_psk(wps
, wps
->dev_password
, wps
->dev_password_len
);
1382 plain
= wpabuf_alloc(200);
1386 msg
= wpabuf_alloc(1000);
1392 if (wps_build_version(msg
) ||
1393 wps_build_msg_type(msg
, WPS_M4
) ||
1394 wps_build_enrollee_nonce(wps
, msg
) ||
1395 wps_build_r_hash(wps
, msg
) ||
1396 wps_build_r_snonce1(wps
, plain
) ||
1397 wps_build_key_wrap_auth(wps
, plain
) ||
1398 wps_build_encr_settings(wps
, msg
, plain
) ||
1399 wps_build_authenticator(wps
, msg
)) {
1406 wps
->state
= RECV_M5
;
1411 static struct wpabuf
* wps_build_m6(struct wps_data
*wps
)
1413 struct wpabuf
*msg
, *plain
;
1415 wpa_printf(MSG_DEBUG
, "WPS: Building Message M6");
1417 plain
= wpabuf_alloc(200);
1421 msg
= wpabuf_alloc(1000);
1427 if (wps_build_version(msg
) ||
1428 wps_build_msg_type(msg
, WPS_M6
) ||
1429 wps_build_enrollee_nonce(wps
, msg
) ||
1430 wps_build_r_snonce2(wps
, plain
) ||
1431 wps_build_key_wrap_auth(wps
, plain
) ||
1432 wps_build_encr_settings(wps
, msg
, plain
) ||
1433 wps_build_authenticator(wps
, msg
)) {
1440 wps
->wps_pin_revealed
= 1;
1441 wps
->state
= RECV_M7
;
1446 static struct wpabuf
* wps_build_m8(struct wps_data
*wps
)
1448 struct wpabuf
*msg
, *plain
;
1450 wpa_printf(MSG_DEBUG
, "WPS: Building Message M8");
1452 plain
= wpabuf_alloc(500);
1456 msg
= wpabuf_alloc(1000);
1462 if (wps_build_version(msg
) ||
1463 wps_build_msg_type(msg
, WPS_M8
) ||
1464 wps_build_enrollee_nonce(wps
, msg
) ||
1465 ((wps
->wps
->ap
|| wps
->er
) && wps_build_cred(wps
, plain
)) ||
1466 (!wps
->wps
->ap
&& !wps
->er
&& wps_build_ap_settings(wps
, plain
)) ||
1467 wps_build_key_wrap_auth(wps
, plain
) ||
1468 wps_build_encr_settings(wps
, msg
, plain
) ||
1469 wps_build_authenticator(wps
, msg
)) {
1476 wps
->state
= RECV_DONE
;
1481 static struct wpabuf
* wps_build_wsc_ack(struct wps_data
*wps
)
1485 wpa_printf(MSG_DEBUG
, "WPS: Building Message WSC_ACK");
1487 msg
= wpabuf_alloc(1000);
1491 if (wps_build_version(msg
) ||
1492 wps_build_msg_type(msg
, WPS_WSC_ACK
) ||
1493 wps_build_enrollee_nonce(wps
, msg
) ||
1494 wps_build_registrar_nonce(wps
, msg
)) {
1503 static struct wpabuf
* wps_build_wsc_nack(struct wps_data
*wps
)
1507 wpa_printf(MSG_DEBUG
, "WPS: Building Message WSC_NACK");
1509 msg
= wpabuf_alloc(1000);
1513 if (wps_build_version(msg
) ||
1514 wps_build_msg_type(msg
, WPS_WSC_NACK
) ||
1515 wps_build_enrollee_nonce(wps
, msg
) ||
1516 wps_build_registrar_nonce(wps
, msg
) ||
1517 wps_build_config_error(msg
, wps
->config_error
)) {
1526 struct wpabuf
* wps_registrar_get_msg(struct wps_data
*wps
,
1527 enum wsc_op_code
*op_code
)
1531 #ifdef CONFIG_WPS_UPNP
1532 if (wps
->wps
->wps_upnp
) {
1533 struct upnp_pending_message
*p
, *prev
= NULL
;
1534 if (wps
->ext_reg
> 1)
1535 wps_registrar_free_pending_m2(wps
->wps
);
1536 p
= wps
->wps
->upnp_msgs
;
1537 /* TODO: check pending message MAC address */
1538 while (p
&& p
->next
) {
1543 wpa_printf(MSG_DEBUG
, "WPS: Use pending message from "
1548 wps
->wps
->upnp_msgs
= NULL
;
1555 *op_code
= WSC_NACK
;
1562 if (wps
->ext_reg
== 0)
1568 wpa_printf(MSG_DEBUG
, "WPS: Using external Registrar, but no "
1569 "pending message available");
1572 #endif /* CONFIG_WPS_UPNP */
1574 switch (wps
->state
) {
1576 if (wps_get_dev_password(wps
) < 0)
1577 msg
= wps_build_m2d(wps
);
1579 msg
= wps_build_m2(wps
);
1583 msg
= wps_build_m2d(wps
);
1587 msg
= wps_build_m4(wps
);
1591 msg
= wps_build_m6(wps
);
1595 msg
= wps_build_m8(wps
);
1599 msg
= wps_build_wsc_ack(wps
);
1603 msg
= wps_build_wsc_nack(wps
);
1604 *op_code
= WSC_NACK
;
1607 wpa_printf(MSG_DEBUG
, "WPS: Unsupported state %d for building "
1608 "a message", wps
->state
);
1613 if (*op_code
== WSC_MSG
&& msg
) {
1614 /* Save a copy of the last message for Authenticator derivation
1616 wpabuf_free(wps
->last_msg
);
1617 wps
->last_msg
= wpabuf_dup(msg
);
1624 static int wps_process_enrollee_nonce(struct wps_data
*wps
, const u8
*e_nonce
)
1626 if (e_nonce
== NULL
) {
1627 wpa_printf(MSG_DEBUG
, "WPS: No Enrollee Nonce received");
1631 os_memcpy(wps
->nonce_e
, e_nonce
, WPS_NONCE_LEN
);
1632 wpa_hexdump(MSG_DEBUG
, "WPS: Enrollee Nonce",
1633 wps
->nonce_e
, WPS_NONCE_LEN
);
1639 static int wps_process_registrar_nonce(struct wps_data
*wps
, const u8
*r_nonce
)
1641 if (r_nonce
== NULL
) {
1642 wpa_printf(MSG_DEBUG
, "WPS: No Registrar Nonce received");
1646 if (os_memcmp(wps
->nonce_r
, r_nonce
, WPS_NONCE_LEN
) != 0) {
1647 wpa_printf(MSG_DEBUG
, "WPS: Invalid Registrar Nonce received");
1655 static int wps_process_uuid_e(struct wps_data
*wps
, const u8
*uuid_e
)
1657 if (uuid_e
== NULL
) {
1658 wpa_printf(MSG_DEBUG
, "WPS: No UUID-E received");
1662 os_memcpy(wps
->uuid_e
, uuid_e
, WPS_UUID_LEN
);
1663 wpa_hexdump(MSG_DEBUG
, "WPS: UUID-E", wps
->uuid_e
, WPS_UUID_LEN
);
1669 static int wps_process_dev_password_id(struct wps_data
*wps
, const u8
*pw_id
)
1671 if (pw_id
== NULL
) {
1672 wpa_printf(MSG_DEBUG
, "WPS: No Device Password ID received");
1676 wps
->dev_pw_id
= WPA_GET_BE16(pw_id
);
1677 wpa_printf(MSG_DEBUG
, "WPS: Device Password ID %d", wps
->dev_pw_id
);
1683 static int wps_process_e_hash1(struct wps_data
*wps
, const u8
*e_hash1
)
1685 if (e_hash1
== NULL
) {
1686 wpa_printf(MSG_DEBUG
, "WPS: No E-Hash1 received");
1690 os_memcpy(wps
->peer_hash1
, e_hash1
, WPS_HASH_LEN
);
1691 wpa_hexdump(MSG_DEBUG
, "WPS: E-Hash1", wps
->peer_hash1
, WPS_HASH_LEN
);
1697 static int wps_process_e_hash2(struct wps_data
*wps
, const u8
*e_hash2
)
1699 if (e_hash2
== NULL
) {
1700 wpa_printf(MSG_DEBUG
, "WPS: No E-Hash2 received");
1704 os_memcpy(wps
->peer_hash2
, e_hash2
, WPS_HASH_LEN
);
1705 wpa_hexdump(MSG_DEBUG
, "WPS: E-Hash2", wps
->peer_hash2
, WPS_HASH_LEN
);
1711 static int wps_process_e_snonce1(struct wps_data
*wps
, const u8
*e_snonce1
)
1713 u8 hash
[SHA256_MAC_LEN
];
1717 if (e_snonce1
== NULL
) {
1718 wpa_printf(MSG_DEBUG
, "WPS: No E-SNonce1 received");
1722 wpa_hexdump_key(MSG_DEBUG
, "WPS: E-SNonce1", e_snonce1
,
1723 WPS_SECRET_NONCE_LEN
);
1725 /* E-Hash1 = HMAC_AuthKey(E-S1 || PSK1 || PK_E || PK_R) */
1726 addr
[0] = e_snonce1
;
1727 len
[0] = WPS_SECRET_NONCE_LEN
;
1728 addr
[1] = wps
->psk1
;
1729 len
[1] = WPS_PSK_LEN
;
1730 addr
[2] = wpabuf_head(wps
->dh_pubkey_e
);
1731 len
[2] = wpabuf_len(wps
->dh_pubkey_e
);
1732 addr
[3] = wpabuf_head(wps
->dh_pubkey_r
);
1733 len
[3] = wpabuf_len(wps
->dh_pubkey_r
);
1734 hmac_sha256_vector(wps
->authkey
, WPS_AUTHKEY_LEN
, 4, addr
, len
, hash
);
1736 if (os_memcmp(wps
->peer_hash1
, hash
, WPS_HASH_LEN
) != 0) {
1737 wpa_printf(MSG_DEBUG
, "WPS: E-Hash1 derived from E-S1 does "
1738 "not match with the pre-committed value");
1739 wps
->config_error
= WPS_CFG_DEV_PASSWORD_AUTH_FAILURE
;
1740 wps_pwd_auth_fail_event(wps
->wps
, 0, 1);
1744 wpa_printf(MSG_DEBUG
, "WPS: Enrollee proved knowledge of the first "
1745 "half of the device password");
1751 static int wps_process_e_snonce2(struct wps_data
*wps
, const u8
*e_snonce2
)
1753 u8 hash
[SHA256_MAC_LEN
];
1757 if (e_snonce2
== NULL
) {
1758 wpa_printf(MSG_DEBUG
, "WPS: No E-SNonce2 received");
1762 wpa_hexdump_key(MSG_DEBUG
, "WPS: E-SNonce2", e_snonce2
,
1763 WPS_SECRET_NONCE_LEN
);
1765 /* E-Hash2 = HMAC_AuthKey(E-S2 || PSK2 || PK_E || PK_R) */
1766 addr
[0] = e_snonce2
;
1767 len
[0] = WPS_SECRET_NONCE_LEN
;
1768 addr
[1] = wps
->psk2
;
1769 len
[1] = WPS_PSK_LEN
;
1770 addr
[2] = wpabuf_head(wps
->dh_pubkey_e
);
1771 len
[2] = wpabuf_len(wps
->dh_pubkey_e
);
1772 addr
[3] = wpabuf_head(wps
->dh_pubkey_r
);
1773 len
[3] = wpabuf_len(wps
->dh_pubkey_r
);
1774 hmac_sha256_vector(wps
->authkey
, WPS_AUTHKEY_LEN
, 4, addr
, len
, hash
);
1776 if (os_memcmp(wps
->peer_hash2
, hash
, WPS_HASH_LEN
) != 0) {
1777 wpa_printf(MSG_DEBUG
, "WPS: E-Hash2 derived from E-S2 does "
1778 "not match with the pre-committed value");
1779 wps_registrar_invalidate_pin(wps
->wps
->registrar
, wps
->uuid_e
);
1780 wps
->config_error
= WPS_CFG_DEV_PASSWORD_AUTH_FAILURE
;
1781 wps_pwd_auth_fail_event(wps
->wps
, 0, 2);
1785 wpa_printf(MSG_DEBUG
, "WPS: Enrollee proved knowledge of the second "
1786 "half of the device password");
1787 wps
->wps_pin_revealed
= 0;
1788 wps_registrar_unlock_pin(wps
->wps
->registrar
, wps
->uuid_e
);
1794 static int wps_process_mac_addr(struct wps_data
*wps
, const u8
*mac_addr
)
1796 if (mac_addr
== NULL
) {
1797 wpa_printf(MSG_DEBUG
, "WPS: No MAC Address received");
1801 wpa_printf(MSG_DEBUG
, "WPS: Enrollee MAC Address " MACSTR
,
1803 os_memcpy(wps
->mac_addr_e
, mac_addr
, ETH_ALEN
);
1804 os_memcpy(wps
->peer_dev
.mac_addr
, mac_addr
, ETH_ALEN
);
1810 static int wps_process_pubkey(struct wps_data
*wps
, const u8
*pk
,
1813 if (pk
== NULL
|| pk_len
== 0) {
1814 wpa_printf(MSG_DEBUG
, "WPS: No Public Key received");
1818 #ifdef CONFIG_WPS_OOB
1819 if (wps
->wps
->oob_conf
.pubkey_hash
!= NULL
) {
1821 u8 hash
[WPS_HASH_LEN
];
1824 sha256_vector(1, addr
, &pk_len
, hash
);
1826 wpabuf_head(wps
->wps
->oob_conf
.pubkey_hash
),
1827 WPS_OOB_PUBKEY_HASH_LEN
) != 0) {
1828 wpa_printf(MSG_ERROR
, "WPS: Public Key hash error");
1832 #endif /* CONFIG_WPS_OOB */
1834 wpabuf_free(wps
->dh_pubkey_e
);
1835 wps
->dh_pubkey_e
= wpabuf_alloc_copy(pk
, pk_len
);
1836 if (wps
->dh_pubkey_e
== NULL
)
1843 static int wps_process_auth_type_flags(struct wps_data
*wps
, const u8
*auth
)
1848 wpa_printf(MSG_DEBUG
, "WPS: No Authentication Type flags "
1853 auth_types
= WPA_GET_BE16(auth
);
1855 wpa_printf(MSG_DEBUG
, "WPS: Enrollee Authentication Type flags 0x%x",
1857 wps
->auth_type
= wps
->wps
->auth_types
& auth_types
;
1858 if (wps
->auth_type
== 0) {
1859 wpa_printf(MSG_DEBUG
, "WPS: No match in supported "
1860 "authentication types (own 0x%x Enrollee 0x%x)",
1861 wps
->wps
->auth_types
, auth_types
);
1862 #ifdef WPS_WORKAROUNDS
1864 * Some deployed implementations seem to advertise incorrect
1865 * information in this attribute. For example, Linksys WRT350N
1866 * seems to have a byteorder bug that breaks this negotiation.
1867 * In order to interoperate with existing implementations,
1868 * assume that the Enrollee supports everything we do.
1870 wpa_printf(MSG_DEBUG
, "WPS: Workaround - assume Enrollee "
1871 "does not advertise supported authentication types "
1873 wps
->auth_type
= wps
->wps
->auth_types
;
1874 #else /* WPS_WORKAROUNDS */
1876 #endif /* WPS_WORKAROUNDS */
1883 static int wps_process_encr_type_flags(struct wps_data
*wps
, const u8
*encr
)
1888 wpa_printf(MSG_DEBUG
, "WPS: No Encryption Type flags "
1893 encr_types
= WPA_GET_BE16(encr
);
1895 wpa_printf(MSG_DEBUG
, "WPS: Enrollee Encryption Type flags 0x%x",
1897 wps
->encr_type
= wps
->wps
->encr_types
& encr_types
;
1898 if (wps
->encr_type
== 0) {
1899 wpa_printf(MSG_DEBUG
, "WPS: No match in supported "
1900 "encryption types (own 0x%x Enrollee 0x%x)",
1901 wps
->wps
->encr_types
, encr_types
);
1902 #ifdef WPS_WORKAROUNDS
1904 * Some deployed implementations seem to advertise incorrect
1905 * information in this attribute. For example, Linksys WRT350N
1906 * seems to have a byteorder bug that breaks this negotiation.
1907 * In order to interoperate with existing implementations,
1908 * assume that the Enrollee supports everything we do.
1910 wpa_printf(MSG_DEBUG
, "WPS: Workaround - assume Enrollee "
1911 "does not advertise supported encryption types "
1913 wps
->encr_type
= wps
->wps
->encr_types
;
1914 #else /* WPS_WORKAROUNDS */
1916 #endif /* WPS_WORKAROUNDS */
1923 static int wps_process_conn_type_flags(struct wps_data
*wps
, const u8
*conn
)
1926 wpa_printf(MSG_DEBUG
, "WPS: No Connection Type flags "
1931 wpa_printf(MSG_DEBUG
, "WPS: Enrollee Connection Type flags 0x%x",
1938 static int wps_process_config_methods(struct wps_data
*wps
, const u8
*methods
)
1942 if (methods
== NULL
) {
1943 wpa_printf(MSG_DEBUG
, "WPS: No Config Methods received");
1947 m
= WPA_GET_BE16(methods
);
1949 wpa_printf(MSG_DEBUG
, "WPS: Enrollee Config Methods 0x%x"
1950 "%s%s%s%s%s%s%s%s%s", m
,
1951 m
& WPS_CONFIG_USBA
? " [USBA]" : "",
1952 m
& WPS_CONFIG_ETHERNET
? " [Ethernet]" : "",
1953 m
& WPS_CONFIG_LABEL
? " [Label]" : "",
1954 m
& WPS_CONFIG_DISPLAY
? " [Display]" : "",
1955 m
& WPS_CONFIG_EXT_NFC_TOKEN
? " [Ext NFC Token]" : "",
1956 m
& WPS_CONFIG_INT_NFC_TOKEN
? " [Int NFC Token]" : "",
1957 m
& WPS_CONFIG_NFC_INTERFACE
? " [NFC]" : "",
1958 m
& WPS_CONFIG_PUSHBUTTON
? " [PBC]" : "",
1959 m
& WPS_CONFIG_KEYPAD
? " [Keypad]" : "");
1961 if (!(m
& WPS_CONFIG_DISPLAY
) && !wps
->use_psk_key
) {
1963 * The Enrollee does not have a display so it is unlikely to be
1964 * able to show the passphrase to a user and as such, could
1965 * benefit from receiving PSK to reduce key derivation time.
1967 wpa_printf(MSG_DEBUG
, "WPS: Prefer PSK format key due to "
1968 "Enrollee not supporting display");
1969 wps
->use_psk_key
= 1;
1976 static int wps_process_wps_state(struct wps_data
*wps
, const u8
*state
)
1978 if (state
== NULL
) {
1979 wpa_printf(MSG_DEBUG
, "WPS: No Wi-Fi Protected Setup State "
1984 wpa_printf(MSG_DEBUG
, "WPS: Enrollee Wi-Fi Protected Setup State %d",
1991 static int wps_process_assoc_state(struct wps_data
*wps
, const u8
*assoc
)
1995 if (assoc
== NULL
) {
1996 wpa_printf(MSG_DEBUG
, "WPS: No Association State received");
2000 a
= WPA_GET_BE16(assoc
);
2001 wpa_printf(MSG_DEBUG
, "WPS: Enrollee Association State %d", a
);
2007 static int wps_process_config_error(struct wps_data
*wps
, const u8
*err
)
2012 wpa_printf(MSG_DEBUG
, "WPS: No Configuration Error received");
2016 e
= WPA_GET_BE16(err
);
2017 wpa_printf(MSG_DEBUG
, "WPS: Enrollee Configuration Error %d", e
);
2023 static enum wps_process_res
wps_process_m1(struct wps_data
*wps
,
2024 struct wps_parse_attr
*attr
)
2026 wpa_printf(MSG_DEBUG
, "WPS: Received M1");
2028 if (wps
->state
!= RECV_M1
) {
2029 wpa_printf(MSG_DEBUG
, "WPS: Unexpected state (%d) for "
2030 "receiving M1", wps
->state
);
2034 if (wps_process_uuid_e(wps
, attr
->uuid_e
) ||
2035 wps_process_mac_addr(wps
, attr
->mac_addr
) ||
2036 wps_process_enrollee_nonce(wps
, attr
->enrollee_nonce
) ||
2037 wps_process_pubkey(wps
, attr
->public_key
, attr
->public_key_len
) ||
2038 wps_process_auth_type_flags(wps
, attr
->auth_type_flags
) ||
2039 wps_process_encr_type_flags(wps
, attr
->encr_type_flags
) ||
2040 wps_process_conn_type_flags(wps
, attr
->conn_type_flags
) ||
2041 wps_process_config_methods(wps
, attr
->config_methods
) ||
2042 wps_process_wps_state(wps
, attr
->wps_state
) ||
2043 wps_process_device_attrs(&wps
->peer_dev
, attr
) ||
2044 wps_process_rf_bands(&wps
->peer_dev
, attr
->rf_bands
) ||
2045 wps_process_assoc_state(wps
, attr
->assoc_state
) ||
2046 wps_process_dev_password_id(wps
, attr
->dev_password_id
) ||
2047 wps_process_config_error(wps
, attr
->config_error
) ||
2048 wps_process_os_version(&wps
->peer_dev
, attr
->os_version
))
2051 if (wps
->dev_pw_id
< 0x10 &&
2052 wps
->dev_pw_id
!= DEV_PW_DEFAULT
&&
2053 wps
->dev_pw_id
!= DEV_PW_USER_SPECIFIED
&&
2054 wps
->dev_pw_id
!= DEV_PW_MACHINE_SPECIFIED
&&
2055 wps
->dev_pw_id
!= DEV_PW_REGISTRAR_SPECIFIED
&&
2056 (wps
->dev_pw_id
!= DEV_PW_PUSHBUTTON
||
2057 !wps
->wps
->registrar
->pbc
)) {
2058 wpa_printf(MSG_DEBUG
, "WPS: Unsupported Device Password ID %d",
2060 wps
->state
= SEND_M2D
;
2061 return WPS_CONTINUE
;
2064 #ifdef CONFIG_WPS_OOB
2065 if (wps
->dev_pw_id
>= 0x10 &&
2066 wps
->dev_pw_id
!= wps
->wps
->oob_dev_pw_id
) {
2067 wpa_printf(MSG_DEBUG
, "WPS: OOB Device Password ID "
2068 "%d mismatch", wps
->dev_pw_id
);
2069 wps
->state
= SEND_M2D
;
2070 return WPS_CONTINUE
;
2072 #endif /* CONFIG_WPS_OOB */
2074 if (wps
->dev_pw_id
== DEV_PW_PUSHBUTTON
) {
2075 if (wps
->wps
->registrar
->force_pbc_overlap
||
2076 wps_registrar_pbc_overlap(wps
->wps
->registrar
,
2077 wps
->mac_addr_e
, wps
->uuid_e
)) {
2078 wpa_printf(MSG_DEBUG
, "WPS: PBC overlap - deny PBC "
2080 wps
->state
= SEND_M2D
;
2081 wps
->config_error
= WPS_CFG_MULTIPLE_PBC_DETECTED
;
2082 wps_pbc_overlap_event(wps
->wps
);
2083 wps
->wps
->registrar
->force_pbc_overlap
= 1;
2084 return WPS_CONTINUE
;
2086 wps_registrar_add_pbc_session(wps
->wps
->registrar
,
2087 wps
->mac_addr_e
, wps
->uuid_e
);
2091 wps
->state
= SEND_M2
;
2092 return WPS_CONTINUE
;
2096 static enum wps_process_res
wps_process_m3(struct wps_data
*wps
,
2097 const struct wpabuf
*msg
,
2098 struct wps_parse_attr
*attr
)
2100 wpa_printf(MSG_DEBUG
, "WPS: Received M3");
2102 if (wps
->state
!= RECV_M3
) {
2103 wpa_printf(MSG_DEBUG
, "WPS: Unexpected state (%d) for "
2104 "receiving M3", wps
->state
);
2105 wps
->state
= SEND_WSC_NACK
;
2106 return WPS_CONTINUE
;
2109 if (wps
->pbc
&& wps
->wps
->registrar
->force_pbc_overlap
) {
2110 wpa_printf(MSG_DEBUG
, "WPS: Reject negotiation due to PBC "
2112 wps
->state
= SEND_WSC_NACK
;
2113 wps
->config_error
= WPS_CFG_MULTIPLE_PBC_DETECTED
;
2114 return WPS_CONTINUE
;
2117 if (wps_process_registrar_nonce(wps
, attr
->registrar_nonce
) ||
2118 wps_process_authenticator(wps
, attr
->authenticator
, msg
) ||
2119 wps_process_e_hash1(wps
, attr
->e_hash1
) ||
2120 wps_process_e_hash2(wps
, attr
->e_hash2
)) {
2121 wps
->state
= SEND_WSC_NACK
;
2122 return WPS_CONTINUE
;
2125 wps
->state
= SEND_M4
;
2126 return WPS_CONTINUE
;
2130 static enum wps_process_res
wps_process_m5(struct wps_data
*wps
,
2131 const struct wpabuf
*msg
,
2132 struct wps_parse_attr
*attr
)
2134 struct wpabuf
*decrypted
;
2135 struct wps_parse_attr eattr
;
2137 wpa_printf(MSG_DEBUG
, "WPS: Received M5");
2139 if (wps
->state
!= RECV_M5
) {
2140 wpa_printf(MSG_DEBUG
, "WPS: Unexpected state (%d) for "
2141 "receiving M5", wps
->state
);
2142 wps
->state
= SEND_WSC_NACK
;
2143 return WPS_CONTINUE
;
2146 if (wps
->pbc
&& wps
->wps
->registrar
->force_pbc_overlap
) {
2147 wpa_printf(MSG_DEBUG
, "WPS: Reject negotiation due to PBC "
2149 wps
->state
= SEND_WSC_NACK
;
2150 wps
->config_error
= WPS_CFG_MULTIPLE_PBC_DETECTED
;
2151 return WPS_CONTINUE
;
2154 if (wps_process_registrar_nonce(wps
, attr
->registrar_nonce
) ||
2155 wps_process_authenticator(wps
, attr
->authenticator
, msg
)) {
2156 wps
->state
= SEND_WSC_NACK
;
2157 return WPS_CONTINUE
;
2160 decrypted
= wps_decrypt_encr_settings(wps
, attr
->encr_settings
,
2161 attr
->encr_settings_len
);
2162 if (decrypted
== NULL
) {
2163 wpa_printf(MSG_DEBUG
, "WPS: Failed to decrypted Encrypted "
2164 "Settings attribute");
2165 wps
->state
= SEND_WSC_NACK
;
2166 return WPS_CONTINUE
;
2169 wpa_printf(MSG_DEBUG
, "WPS: Processing decrypted Encrypted Settings "
2171 if (wps_parse_msg(decrypted
, &eattr
) < 0 ||
2172 wps_process_key_wrap_auth(wps
, decrypted
, eattr
.key_wrap_auth
) ||
2173 wps_process_e_snonce1(wps
, eattr
.e_snonce1
)) {
2174 wpabuf_free(decrypted
);
2175 wps
->state
= SEND_WSC_NACK
;
2176 return WPS_CONTINUE
;
2178 wpabuf_free(decrypted
);
2180 wps
->state
= SEND_M6
;
2181 return WPS_CONTINUE
;
2185 static void wps_sta_cred_cb(struct wps_data
*wps
)
2188 * Update credential to only include a single authentication and
2189 * encryption type in case the AP configuration includes more than one
2192 if (wps
->cred
.auth_type
& WPS_AUTH_WPA2PSK
)
2193 wps
->cred
.auth_type
= WPS_AUTH_WPA2PSK
;
2194 else if (wps
->cred
.auth_type
& WPS_AUTH_WPAPSK
)
2195 wps
->cred
.auth_type
= WPS_AUTH_WPAPSK
;
2196 if (wps
->cred
.encr_type
& WPS_ENCR_AES
)
2197 wps
->cred
.encr_type
= WPS_ENCR_AES
;
2198 else if (wps
->cred
.encr_type
& WPS_ENCR_TKIP
)
2199 wps
->cred
.encr_type
= WPS_ENCR_TKIP
;
2200 wpa_printf(MSG_DEBUG
, "WPS: Update local configuration based on the "
2201 "AP configuration");
2202 if (wps
->wps
->cred_cb
)
2203 wps
->wps
->cred_cb(wps
->wps
->cb_ctx
, &wps
->cred
);
2207 static void wps_cred_update(struct wps_credential
*dst
,
2208 struct wps_credential
*src
)
2210 os_memcpy(dst
->ssid
, src
->ssid
, sizeof(dst
->ssid
));
2211 dst
->ssid_len
= src
->ssid_len
;
2212 dst
->auth_type
= src
->auth_type
;
2213 dst
->encr_type
= src
->encr_type
;
2214 dst
->key_idx
= src
->key_idx
;
2215 os_memcpy(dst
->key
, src
->key
, sizeof(dst
->key
));
2216 dst
->key_len
= src
->key_len
;
2220 static int wps_process_ap_settings_r(struct wps_data
*wps
,
2221 struct wps_parse_attr
*attr
)
2223 if (wps
->wps
->ap
|| wps
->er
)
2226 /* AP Settings Attributes in M7 when Enrollee is an AP */
2227 if (wps_process_ap_settings(attr
, &wps
->cred
) < 0)
2230 wpa_printf(MSG_INFO
, "WPS: Received old AP configuration from AP");
2232 if (wps
->new_ap_settings
) {
2233 wpa_printf(MSG_INFO
, "WPS: Update AP configuration based on "
2235 wps_cred_update(&wps
->cred
, wps
->new_ap_settings
);
2239 * Use the AP PIN only to receive the current AP settings, not
2240 * to reconfigure the AP.
2242 if (wps
->ap_settings_cb
) {
2243 wps
->ap_settings_cb(wps
->ap_settings_cb_ctx
,
2247 wps_sta_cred_cb(wps
);
2253 static enum wps_process_res
wps_process_m7(struct wps_data
*wps
,
2254 const struct wpabuf
*msg
,
2255 struct wps_parse_attr
*attr
)
2257 struct wpabuf
*decrypted
;
2258 struct wps_parse_attr eattr
;
2260 wpa_printf(MSG_DEBUG
, "WPS: Received M7");
2262 if (wps
->state
!= RECV_M7
) {
2263 wpa_printf(MSG_DEBUG
, "WPS: Unexpected state (%d) for "
2264 "receiving M7", wps
->state
);
2265 wps
->state
= SEND_WSC_NACK
;
2266 return WPS_CONTINUE
;
2269 if (wps
->pbc
&& wps
->wps
->registrar
->force_pbc_overlap
) {
2270 wpa_printf(MSG_DEBUG
, "WPS: Reject negotiation due to PBC "
2272 wps
->state
= SEND_WSC_NACK
;
2273 wps
->config_error
= WPS_CFG_MULTIPLE_PBC_DETECTED
;
2274 return WPS_CONTINUE
;
2277 if (wps_process_registrar_nonce(wps
, attr
->registrar_nonce
) ||
2278 wps_process_authenticator(wps
, attr
->authenticator
, msg
)) {
2279 wps
->state
= SEND_WSC_NACK
;
2280 return WPS_CONTINUE
;
2283 decrypted
= wps_decrypt_encr_settings(wps
, attr
->encr_settings
,
2284 attr
->encr_settings_len
);
2285 if (decrypted
== NULL
) {
2286 wpa_printf(MSG_DEBUG
, "WPS: Failed to decrypt Encrypted "
2287 "Settings attribute");
2288 wps
->state
= SEND_WSC_NACK
;
2289 return WPS_CONTINUE
;
2292 wpa_printf(MSG_DEBUG
, "WPS: Processing decrypted Encrypted Settings "
2294 if (wps_parse_msg(decrypted
, &eattr
) < 0 ||
2295 wps_process_key_wrap_auth(wps
, decrypted
, eattr
.key_wrap_auth
) ||
2296 wps_process_e_snonce2(wps
, eattr
.e_snonce2
) ||
2297 wps_process_ap_settings_r(wps
, &eattr
)) {
2298 wpabuf_free(decrypted
);
2299 wps
->state
= SEND_WSC_NACK
;
2300 return WPS_CONTINUE
;
2303 wpabuf_free(decrypted
);
2305 wps
->state
= SEND_M8
;
2306 return WPS_CONTINUE
;
2310 static enum wps_process_res
wps_process_wsc_msg(struct wps_data
*wps
,
2311 const struct wpabuf
*msg
)
2313 struct wps_parse_attr attr
;
2314 enum wps_process_res ret
= WPS_CONTINUE
;
2316 wpa_printf(MSG_DEBUG
, "WPS: Received WSC_MSG");
2318 if (wps_parse_msg(msg
, &attr
) < 0)
2321 if (!wps_version_supported(attr
.version
)) {
2322 wpa_printf(MSG_DEBUG
, "WPS: Unsupported message version 0x%x",
2323 attr
.version
? *attr
.version
: 0);
2327 if (attr
.msg_type
== NULL
) {
2328 wpa_printf(MSG_DEBUG
, "WPS: No Message Type attribute");
2332 if (*attr
.msg_type
!= WPS_M1
&&
2333 (attr
.registrar_nonce
== NULL
||
2334 os_memcmp(wps
->nonce_r
, attr
.registrar_nonce
,
2335 WPS_NONCE_LEN
!= 0))) {
2336 wpa_printf(MSG_DEBUG
, "WPS: Mismatch in registrar nonce");
2340 switch (*attr
.msg_type
) {
2342 #ifdef CONFIG_WPS_UPNP
2343 if (wps
->wps
->wps_upnp
&& attr
.mac_addr
) {
2344 /* Remove old pending messages when starting new run */
2345 wps_free_pending_msgs(wps
->wps
->upnp_msgs
);
2346 wps
->wps
->upnp_msgs
= NULL
;
2348 upnp_wps_device_send_wlan_event(
2349 wps
->wps
->wps_upnp
, attr
.mac_addr
,
2350 UPNP_WPS_WLANEVENT_TYPE_EAP
, msg
);
2352 #endif /* CONFIG_WPS_UPNP */
2353 ret
= wps_process_m1(wps
, &attr
);
2356 ret
= wps_process_m3(wps
, msg
, &attr
);
2357 if (ret
== WPS_FAILURE
|| wps
->state
== SEND_WSC_NACK
)
2358 wps_fail_event(wps
->wps
, WPS_M3
);
2361 ret
= wps_process_m5(wps
, msg
, &attr
);
2362 if (ret
== WPS_FAILURE
|| wps
->state
== SEND_WSC_NACK
)
2363 wps_fail_event(wps
->wps
, WPS_M5
);
2366 ret
= wps_process_m7(wps
, msg
, &attr
);
2367 if (ret
== WPS_FAILURE
|| wps
->state
== SEND_WSC_NACK
)
2368 wps_fail_event(wps
->wps
, WPS_M7
);
2371 wpa_printf(MSG_DEBUG
, "WPS: Unsupported Message Type %d",
2376 if (ret
== WPS_CONTINUE
) {
2377 /* Save a copy of the last message for Authenticator derivation
2379 wpabuf_free(wps
->last_msg
);
2380 wps
->last_msg
= wpabuf_dup(msg
);
2387 static enum wps_process_res
wps_process_wsc_ack(struct wps_data
*wps
,
2388 const struct wpabuf
*msg
)
2390 struct wps_parse_attr attr
;
2392 wpa_printf(MSG_DEBUG
, "WPS: Received WSC_ACK");
2394 if (wps_parse_msg(msg
, &attr
) < 0)
2397 if (!wps_version_supported(attr
.version
)) {
2398 wpa_printf(MSG_DEBUG
, "WPS: Unsupported message version 0x%x",
2399 attr
.version
? *attr
.version
: 0);
2403 if (attr
.msg_type
== NULL
) {
2404 wpa_printf(MSG_DEBUG
, "WPS: No Message Type attribute");
2408 if (*attr
.msg_type
!= WPS_WSC_ACK
) {
2409 wpa_printf(MSG_DEBUG
, "WPS: Invalid Message Type %d",
2414 #ifdef CONFIG_WPS_UPNP
2415 if (wps
->wps
->wps_upnp
&& wps
->ext_reg
&& wps
->state
== RECV_M2D_ACK
&&
2416 upnp_wps_subscribers(wps
->wps
->wps_upnp
)) {
2417 if (wps
->wps
->upnp_msgs
)
2418 return WPS_CONTINUE
;
2419 wpa_printf(MSG_DEBUG
, "WPS: Wait for response from an "
2420 "external Registrar");
2423 #endif /* CONFIG_WPS_UPNP */
2425 if (attr
.registrar_nonce
== NULL
||
2426 os_memcmp(wps
->nonce_r
, attr
.registrar_nonce
, WPS_NONCE_LEN
!= 0))
2428 wpa_printf(MSG_DEBUG
, "WPS: Mismatch in registrar nonce");
2432 if (attr
.enrollee_nonce
== NULL
||
2433 os_memcmp(wps
->nonce_e
, attr
.enrollee_nonce
, WPS_NONCE_LEN
!= 0)) {
2434 wpa_printf(MSG_DEBUG
, "WPS: Mismatch in enrollee nonce");
2438 if (wps
->state
== RECV_M2D_ACK
) {
2439 #ifdef CONFIG_WPS_UPNP
2440 if (wps
->wps
->wps_upnp
&&
2441 upnp_wps_subscribers(wps
->wps
->wps_upnp
)) {
2442 if (wps
->wps
->upnp_msgs
)
2443 return WPS_CONTINUE
;
2444 if (wps
->ext_reg
== 0)
2446 wpa_printf(MSG_DEBUG
, "WPS: Wait for response from an "
2447 "external Registrar");
2450 #endif /* CONFIG_WPS_UPNP */
2452 wpa_printf(MSG_DEBUG
, "WPS: No more registrars available - "
2453 "terminate negotiation");
2460 static enum wps_process_res
wps_process_wsc_nack(struct wps_data
*wps
,
2461 const struct wpabuf
*msg
)
2463 struct wps_parse_attr attr
;
2466 wpa_printf(MSG_DEBUG
, "WPS: Received WSC_NACK");
2468 old_state
= wps
->state
;
2469 wps
->state
= SEND_WSC_NACK
;
2471 if (wps_parse_msg(msg
, &attr
) < 0)
2474 if (!wps_version_supported(attr
.version
)) {
2475 wpa_printf(MSG_DEBUG
, "WPS: Unsupported message version 0x%x",
2476 attr
.version
? *attr
.version
: 0);
2480 if (attr
.msg_type
== NULL
) {
2481 wpa_printf(MSG_DEBUG
, "WPS: No Message Type attribute");
2485 if (*attr
.msg_type
!= WPS_WSC_NACK
) {
2486 wpa_printf(MSG_DEBUG
, "WPS: Invalid Message Type %d",
2491 #ifdef CONFIG_WPS_UPNP
2492 if (wps
->wps
->wps_upnp
&& wps
->ext_reg
) {
2493 wpa_printf(MSG_DEBUG
, "WPS: Negotiation using external "
2494 "Registrar terminated by the Enrollee");
2497 #endif /* CONFIG_WPS_UPNP */
2499 if (attr
.registrar_nonce
== NULL
||
2500 os_memcmp(wps
->nonce_r
, attr
.registrar_nonce
, WPS_NONCE_LEN
!= 0))
2502 wpa_printf(MSG_DEBUG
, "WPS: Mismatch in registrar nonce");
2506 if (attr
.enrollee_nonce
== NULL
||
2507 os_memcmp(wps
->nonce_e
, attr
.enrollee_nonce
, WPS_NONCE_LEN
!= 0)) {
2508 wpa_printf(MSG_DEBUG
, "WPS: Mismatch in enrollee nonce");
2512 if (attr
.config_error
== NULL
) {
2513 wpa_printf(MSG_DEBUG
, "WPS: No Configuration Error attribute "
2518 wpa_printf(MSG_DEBUG
, "WPS: Enrollee terminated negotiation with "
2519 "Configuration Error %d", WPA_GET_BE16(attr
.config_error
));
2521 switch (old_state
) {
2523 wps_fail_event(wps
->wps
, WPS_M2
);
2526 wps_fail_event(wps
->wps
, WPS_M4
);
2529 wps_fail_event(wps
->wps
, WPS_M6
);
2532 wps_fail_event(wps
->wps
, WPS_M8
);
2542 static enum wps_process_res
wps_process_wsc_done(struct wps_data
*wps
,
2543 const struct wpabuf
*msg
)
2545 struct wps_parse_attr attr
;
2547 wpa_printf(MSG_DEBUG
, "WPS: Received WSC_Done");
2549 if (wps
->state
!= RECV_DONE
&&
2550 (!wps
->wps
->wps_upnp
|| !wps
->ext_reg
)) {
2551 wpa_printf(MSG_DEBUG
, "WPS: Unexpected state (%d) for "
2552 "receiving WSC_Done", wps
->state
);
2556 if (wps_parse_msg(msg
, &attr
) < 0)
2559 if (!wps_version_supported(attr
.version
)) {
2560 wpa_printf(MSG_DEBUG
, "WPS: Unsupported message version 0x%x",
2561 attr
.version
? *attr
.version
: 0);
2565 if (attr
.msg_type
== NULL
) {
2566 wpa_printf(MSG_DEBUG
, "WPS: No Message Type attribute");
2570 if (*attr
.msg_type
!= WPS_WSC_DONE
) {
2571 wpa_printf(MSG_DEBUG
, "WPS: Invalid Message Type %d",
2576 #ifdef CONFIG_WPS_UPNP
2577 if (wps
->wps
->wps_upnp
&& wps
->ext_reg
) {
2578 wpa_printf(MSG_DEBUG
, "WPS: Negotiation using external "
2579 "Registrar completed successfully");
2580 wps_device_store(wps
->wps
->registrar
, &wps
->peer_dev
,
2584 #endif /* CONFIG_WPS_UPNP */
2586 if (attr
.registrar_nonce
== NULL
||
2587 os_memcmp(wps
->nonce_r
, attr
.registrar_nonce
, WPS_NONCE_LEN
!= 0))
2589 wpa_printf(MSG_DEBUG
, "WPS: Mismatch in registrar nonce");
2593 if (attr
.enrollee_nonce
== NULL
||
2594 os_memcmp(wps
->nonce_e
, attr
.enrollee_nonce
, WPS_NONCE_LEN
!= 0)) {
2595 wpa_printf(MSG_DEBUG
, "WPS: Mismatch in enrollee nonce");
2599 wpa_printf(MSG_DEBUG
, "WPS: Negotiation completed successfully");
2600 wps_device_store(wps
->wps
->registrar
, &wps
->peer_dev
,
2603 if (wps
->wps
->wps_state
== WPS_STATE_NOT_CONFIGURED
&& wps
->new_psk
&&
2604 wps
->wps
->ap
&& !wps
->wps
->registrar
->disable_auto_conf
) {
2605 struct wps_credential cred
;
2607 wpa_printf(MSG_DEBUG
, "WPS: Moving to Configured state based "
2608 "on first Enrollee connection");
2610 os_memset(&cred
, 0, sizeof(cred
));
2611 os_memcpy(cred
.ssid
, wps
->wps
->ssid
, wps
->wps
->ssid_len
);
2612 cred
.ssid_len
= wps
->wps
->ssid_len
;
2613 cred
.auth_type
= WPS_AUTH_WPAPSK
| WPS_AUTH_WPA2PSK
;
2614 cred
.encr_type
= WPS_ENCR_TKIP
| WPS_ENCR_AES
;
2615 os_memcpy(cred
.key
, wps
->new_psk
, wps
->new_psk_len
);
2616 cred
.key_len
= wps
->new_psk_len
;
2618 wps
->wps
->wps_state
= WPS_STATE_CONFIGURED
;
2619 wpa_hexdump_ascii_key(MSG_DEBUG
,
2620 "WPS: Generated random passphrase",
2621 wps
->new_psk
, wps
->new_psk_len
);
2622 if (wps
->wps
->cred_cb
)
2623 wps
->wps
->cred_cb(wps
->wps
->cb_ctx
, &cred
);
2625 os_free(wps
->new_psk
);
2626 wps
->new_psk
= NULL
;
2629 if (!wps
->wps
->ap
&& !wps
->er
)
2630 wps_sta_cred_cb(wps
);
2633 if (wps_cb_new_psk(wps
->wps
->registrar
, wps
->mac_addr_e
,
2634 wps
->new_psk
, wps
->new_psk_len
)) {
2635 wpa_printf(MSG_DEBUG
, "WPS: Failed to configure the "
2638 os_free(wps
->new_psk
);
2639 wps
->new_psk
= NULL
;
2642 wps_cb_reg_success(wps
->wps
->registrar
, wps
->mac_addr_e
, wps
->uuid_e
);
2645 wps_registrar_remove_pbc_session(wps
->wps
->registrar
,
2646 wps
->mac_addr_e
, wps
->uuid_e
);
2647 wps_registrar_pbc_completed(wps
->wps
->registrar
);
2649 wps_registrar_pin_completed(wps
->wps
->registrar
);
2652 wps_success_event(wps
->wps
);
2658 enum wps_process_res
wps_registrar_process_msg(struct wps_data
*wps
,
2659 enum wsc_op_code op_code
,
2660 const struct wpabuf
*msg
)
2662 enum wps_process_res ret
;
2664 wpa_printf(MSG_DEBUG
, "WPS: Processing received message (len=%lu "
2666 (unsigned long) wpabuf_len(msg
), op_code
);
2668 #ifdef CONFIG_WPS_UPNP
2669 if (wps
->wps
->wps_upnp
&& op_code
== WSC_MSG
&& wps
->ext_reg
== 1) {
2670 struct wps_parse_attr attr
;
2671 if (wps_parse_msg(msg
, &attr
) == 0 && attr
.msg_type
&&
2672 *attr
.msg_type
== WPS_M3
)
2673 wps
->ext_reg
= 2; /* past M2/M2D phase */
2675 if (wps
->ext_reg
> 1)
2676 wps_registrar_free_pending_m2(wps
->wps
);
2677 if (wps
->wps
->wps_upnp
&& wps
->ext_reg
&&
2678 wps
->wps
->upnp_msgs
== NULL
&&
2679 (op_code
== WSC_MSG
|| op_code
== WSC_Done
|| op_code
== WSC_NACK
))
2681 struct wps_parse_attr attr
;
2683 if (wps_parse_msg(msg
, &attr
) < 0 || attr
.msg_type
== NULL
)
2686 type
= *attr
.msg_type
;
2687 wpa_printf(MSG_DEBUG
, "WPS: Sending received message (type %d)"
2688 " to external Registrar for processing", type
);
2689 upnp_wps_device_send_wlan_event(wps
->wps
->wps_upnp
,
2691 UPNP_WPS_WLANEVENT_TYPE_EAP
,
2693 if (op_code
== WSC_MSG
)
2695 } else if (wps
->wps
->wps_upnp
&& wps
->ext_reg
&& op_code
== WSC_MSG
) {
2696 wpa_printf(MSG_DEBUG
, "WPS: Skip internal processing - using "
2697 "external Registrar");
2698 return WPS_CONTINUE
;
2700 #endif /* CONFIG_WPS_UPNP */
2704 return wps_process_wsc_msg(wps
, msg
);
2706 return wps_process_wsc_ack(wps
, msg
);
2708 return wps_process_wsc_nack(wps
, msg
);
2710 ret
= wps_process_wsc_done(wps
, msg
);
2711 if (ret
== WPS_FAILURE
) {
2712 wps
->state
= SEND_WSC_NACK
;
2713 wps_fail_event(wps
->wps
, WPS_WSC_DONE
);
2717 wpa_printf(MSG_DEBUG
, "WPS: Unsupported op_code %d", op_code
);
2723 int wps_registrar_update_ie(struct wps_registrar
*reg
)
2725 return wps_set_ie(reg
);
2729 static void wps_registrar_set_selected_timeout(void *eloop_ctx
,
2732 struct wps_registrar
*reg
= eloop_ctx
;
2734 wpa_printf(MSG_DEBUG
, "WPS: Selected Registrar timeout - "
2735 "unselect internal Registrar");
2736 reg
->selected_registrar
= 0;
2738 wps_registrar_selected_registrar_changed(reg
);
2742 #ifdef CONFIG_WPS_UPNP
2743 static void wps_registrar_sel_reg_add(struct wps_registrar
*reg
,
2744 struct subscription
*s
)
2746 wpa_printf(MSG_DEBUG
, "WPS: External Registrar selected (dev_pw_id=%d "
2747 "config_methods=0x%x)",
2748 s
->dev_password_id
, s
->config_methods
);
2749 reg
->sel_reg_union
= 1;
2750 if (reg
->sel_reg_dev_password_id_override
!= DEV_PW_PUSHBUTTON
)
2751 reg
->sel_reg_dev_password_id_override
= s
->dev_password_id
;
2752 if (reg
->sel_reg_config_methods_override
== -1)
2753 reg
->sel_reg_config_methods_override
= 0;
2754 reg
->sel_reg_config_methods_override
|= s
->config_methods
;
2756 #endif /* CONFIG_WPS_UPNP */
2759 static void wps_registrar_sel_reg_union(struct wps_registrar
*reg
)
2761 #ifdef CONFIG_WPS_UPNP
2762 struct subscription
*s
;
2764 if (reg
->wps
->wps_upnp
== NULL
)
2767 dl_list_for_each(s
, ®
->wps
->wps_upnp
->subscriptions
,
2768 struct subscription
, list
) {
2769 struct subscr_addr
*sa
;
2770 sa
= dl_list_first(&s
->addr_list
, struct subscr_addr
, list
);
2772 wpa_printf(MSG_DEBUG
, "WPS: External Registrar %s:%d",
2773 inet_ntoa(sa
->saddr
.sin_addr
),
2774 ntohs(sa
->saddr
.sin_port
));
2776 if (s
->selected_registrar
)
2777 wps_registrar_sel_reg_add(reg
, s
);
2779 wpa_printf(MSG_DEBUG
, "WPS: External Registrar not "
2782 #endif /* CONFIG_WPS_UPNP */
2787 * wps_registrar_selected_registrar_changed - SetSelectedRegistrar change
2788 * @reg: Registrar data from wps_registrar_init()
2790 * This function is called when selected registrar state changes, e.g., when an
2791 * AP receives a SetSelectedRegistrar UPnP message.
2793 void wps_registrar_selected_registrar_changed(struct wps_registrar
*reg
)
2795 wpa_printf(MSG_DEBUG
, "WPS: Selected registrar information changed");
2797 reg
->sel_reg_union
= reg
->selected_registrar
;
2798 reg
->sel_reg_dev_password_id_override
= -1;
2799 reg
->sel_reg_config_methods_override
= -1;
2800 if (reg
->selected_registrar
) {
2801 reg
->sel_reg_config_methods_override
=
2802 reg
->wps
->config_methods
& ~WPS_CONFIG_PUSHBUTTON
;
2804 reg
->sel_reg_dev_password_id_override
=
2806 reg
->sel_reg_config_methods_override
|=
2807 WPS_CONFIG_PUSHBUTTON
;
2809 wpa_printf(MSG_DEBUG
, "WPS: Internal Registrar selected "
2810 "(pbc=%d)", reg
->pbc
);
2812 wpa_printf(MSG_DEBUG
, "WPS: Internal Registrar not selected");
2814 wps_registrar_sel_reg_union(reg
);
2817 wps_cb_set_sel_reg(reg
);
2821 int wps_registrar_get_info(struct wps_registrar
*reg
, const u8
*addr
,
2822 char *buf
, size_t buflen
)
2824 struct wps_registrar_device
*d
;
2827 char devtype
[WPS_DEV_TYPE_BUFSIZE
];
2829 d
= wps_device_get(reg
, addr
);
2832 if (uuid_bin2str(d
->uuid
, uuid
, sizeof(uuid
)))
2835 ret
= os_snprintf(buf
+ len
, buflen
- len
,
2837 "wpsPrimaryDeviceType=%s\n"
2838 "wpsDeviceName=%s\n"
2839 "wpsManufacturer=%s\n"
2841 "wpsModelNumber=%s\n"
2842 "wpsSerialNumber=%s\n",
2844 wps_dev_type_bin2str(d
->dev
.pri_dev_type
, devtype
,
2846 d
->dev
.device_name
? d
->dev
.device_name
: "",
2847 d
->dev
.manufacturer
? d
->dev
.manufacturer
: "",
2848 d
->dev
.model_name
? d
->dev
.model_name
: "",
2849 d
->dev
.model_number
? d
->dev
.model_number
: "",
2850 d
->dev
.serial_number
? d
->dev
.serial_number
: "");
2851 if (ret
< 0 || (size_t) ret
>= buflen
- len
)