2 * Wi-Fi Protected Setup
3 * Copyright (c) 2007-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.
18 #include "crypto/dh_group5.h"
19 #include "common/ieee802_11_defs.h"
21 #include "wps_dev_attr.h"
25 * wps_init - Initialize WPS Registration protocol data
26 * @cfg: WPS configuration
27 * Returns: Pointer to allocated data or %NULL on failure
29 * This function is used to initialize WPS data for a registration protocol
30 * instance (i.e., each run of registration protocol as a Registrar of
31 * Enrollee. The caller is responsible for freeing this data after the
32 * registration run has been completed by calling wps_deinit().
34 struct wps_data * wps_init(const struct wps_config *cfg)
36 struct wps_data *data = os_zalloc(sizeof(*data));
40 data->registrar = cfg->registrar;
42 os_memcpy(data->uuid_r, cfg->wps->uuid, WPS_UUID_LEN);
44 os_memcpy(data->mac_addr_e, cfg->wps->dev.mac_addr, ETH_ALEN);
45 os_memcpy(data->uuid_e, cfg->wps->uuid, WPS_UUID_LEN);
48 data->dev_pw_id = data->wps->oob_dev_pw_id == 0 ?
49 DEV_PW_DEFAULT : data->wps->oob_dev_pw_id;
50 data->dev_password = os_malloc(cfg->pin_len);
51 if (data->dev_password == NULL) {
55 os_memcpy(data->dev_password, cfg->pin, cfg->pin_len);
56 data->dev_password_len = cfg->pin_len;
61 /* Use special PIN '00000000' for PBC */
62 data->dev_pw_id = DEV_PW_PUSHBUTTON;
63 os_free(data->dev_password);
64 data->dev_password = os_malloc(8);
65 if (data->dev_password == NULL) {
69 os_memset(data->dev_password, '0', 8);
70 data->dev_password_len = 8;
73 data->state = data->registrar ? RECV_M1 : SEND_M1;
75 if (cfg->assoc_wps_ie) {
76 struct wps_parse_attr attr;
77 wpa_hexdump_buf(MSG_DEBUG, "WPS: WPS IE from (Re)AssocReq",
79 if (wps_parse_msg(cfg->assoc_wps_ie, &attr) < 0) {
80 wpa_printf(MSG_DEBUG, "WPS: Failed to parse WPS IE "
82 } else if (attr.request_type == NULL) {
83 wpa_printf(MSG_DEBUG, "WPS: No Request Type attribute "
84 "in (Re)AssocReq WPS IE");
86 wpa_printf(MSG_DEBUG, "WPS: Request Type (from WPS IE "
87 "in (Re)AssocReq WPS IE): %d",
89 data->request_type = *attr.request_type;
93 if (cfg->new_ap_settings) {
94 data->new_ap_settings =
95 os_malloc(sizeof(*data->new_ap_settings));
96 if (data->new_ap_settings == NULL) {
100 os_memcpy(data->new_ap_settings, cfg->new_ap_settings,
101 sizeof(*data->new_ap_settings));
105 os_memcpy(data->peer_dev.mac_addr, cfg->peer_addr, ETH_ALEN);
112 * wps_deinit - Deinitialize WPS Registration protocol data
113 * @data: WPS Registration protocol data from wps_init()
115 void wps_deinit(struct wps_data *data)
117 if (data->wps_pin_revealed) {
118 wpa_printf(MSG_DEBUG, "WPS: Full PIN information revealed and "
119 "negotiation failed");
121 wps_registrar_invalidate_pin(data->wps->registrar,
123 } else if (data->registrar)
124 wps_registrar_unlock_pin(data->wps->registrar, data->uuid_e);
126 wpabuf_free(data->dh_privkey);
127 wpabuf_free(data->dh_pubkey_e);
128 wpabuf_free(data->dh_pubkey_r);
129 wpabuf_free(data->last_msg);
130 os_free(data->dev_password);
131 os_free(data->new_psk);
132 wps_device_data_free(&data->peer_dev);
133 os_free(data->new_ap_settings);
134 dh5_free(data->dh_ctx);
140 * wps_process_msg - Process a WPS message
141 * @wps: WPS Registration protocol data from wps_init()
142 * @op_code: Message OP Code
144 * Returns: Processing result
146 * This function is used to process WPS messages with OP Codes WSC_ACK,
147 * WSC_NACK, WSC_MSG, and WSC_Done. The caller (e.g., EAP server/peer) is
148 * responsible for reassembling the messages before calling this function.
149 * Response to this message is built by calling wps_get_msg().
151 enum wps_process_res wps_process_msg(struct wps_data *wps,
152 enum wsc_op_code op_code,
153 const struct wpabuf *msg)
156 return wps_registrar_process_msg(wps, op_code, msg);
158 return wps_enrollee_process_msg(wps, op_code, msg);
163 * wps_get_msg - Build a WPS message
164 * @wps: WPS Registration protocol data from wps_init()
165 * @op_code: Buffer for returning message OP Code
166 * Returns: The generated WPS message or %NULL on failure
168 * This function is used to build a response to a message processed by calling
169 * wps_process_msg(). The caller is responsible for freeing the buffer.
171 struct wpabuf * wps_get_msg(struct wps_data *wps, enum wsc_op_code *op_code)
174 return wps_registrar_get_msg(wps, op_code);
176 return wps_enrollee_get_msg(wps, op_code);
181 * wps_is_selected_pbc_registrar - Check whether WPS IE indicates active PBC
182 * @msg: WPS IE contents from Beacon or Probe Response frame
183 * Returns: 1 if PBC Registrar is active, 0 if not
185 int wps_is_selected_pbc_registrar(const struct wpabuf *msg)
187 struct wps_parse_attr attr;
190 * In theory, this could also verify that attr.sel_reg_config_methods
191 * includes WPS_CONFIG_PUSHBUTTON, but some deployed AP implementations
192 * do not set Selected Registrar Config Methods attribute properly, so
193 * it is safer to just use Device Password ID here.
196 if (wps_parse_msg(msg, &attr) < 0 ||
197 !attr.selected_registrar || *attr.selected_registrar == 0 ||
198 !attr.dev_password_id ||
199 WPA_GET_BE16(attr.dev_password_id) != DEV_PW_PUSHBUTTON)
207 * wps_is_selected_pin_registrar - Check whether WPS IE indicates active PIN
208 * @msg: WPS IE contents from Beacon or Probe Response frame
209 * Returns: 1 if PIN Registrar is active, 0 if not
211 int wps_is_selected_pin_registrar(const struct wpabuf *msg)
213 struct wps_parse_attr attr;
216 * In theory, this could also verify that attr.sel_reg_config_methods
217 * includes WPS_CONFIG_LABEL, WPS_CONFIG_DISPLAY, or WPS_CONFIG_KEYPAD,
218 * but some deployed AP implementations do not set Selected Registrar
219 * Config Methods attribute properly, so it is safer to just use
220 * Device Password ID here.
223 if (wps_parse_msg(msg, &attr) < 0)
226 if (!attr.selected_registrar || *attr.selected_registrar == 0)
229 if (attr.dev_password_id != NULL &&
230 WPA_GET_BE16(attr.dev_password_id) == DEV_PW_PUSHBUTTON)
238 * wps_get_uuid_e - Get UUID-E from WPS IE
239 * @msg: WPS IE contents from Beacon or Probe Response frame
240 * Returns: Pointer to UUID-E or %NULL if not included
242 * The returned pointer is to the msg contents and it remains valid only as
243 * long as the msg buffer is valid.
245 const u8 * wps_get_uuid_e(const struct wpabuf *msg)
247 struct wps_parse_attr attr;
249 if (wps_parse_msg(msg, &attr) < 0)
256 * wps_build_assoc_req_ie - Build WPS IE for (Re)Association Request
257 * @req_type: Value for Request Type attribute
258 * Returns: WPS IE or %NULL on failure
260 * The caller is responsible for freeing the buffer.
262 struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type)
267 wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for (Re)Association "
269 ie = wpabuf_alloc(100);
273 wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC);
274 len = wpabuf_put(ie, 1);
275 wpabuf_put_be32(ie, WPS_DEV_OUI_WFA);
277 if (wps_build_version(ie) ||
278 wps_build_req_type(ie, req_type)) {
283 *len = wpabuf_len(ie) - 2;
290 * wps_build_probe_req_ie - Build WPS IE for Probe Request
291 * @pbc: Whether searching for PBC mode APs
292 * @dev: Device attributes
294 * @req_type: Value for Request Type attribute
295 * Returns: WPS IE or %NULL on failure
297 * The caller is responsible for freeing the buffer.
299 struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev,
301 enum wps_request_type req_type)
307 wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for Probe Request");
309 ie = wpabuf_alloc(200);
313 wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC);
314 len = wpabuf_put(ie, 1);
315 wpabuf_put_be32(ie, WPS_DEV_OUI_WFA);
318 methods = WPS_CONFIG_PUSHBUTTON;
320 methods = WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY |
322 #ifdef CONFIG_WPS_UFD
323 methods |= WPS_CONFIG_USBA;
324 #endif /* CONFIG_WPS_UFD */
325 #ifdef CONFIG_WPS_NFC
326 methods |= WPS_CONFIG_NFC_INTERFACE;
327 #endif /* CONFIG_WPS_NFC */
330 if (wps_build_version(ie) ||
331 wps_build_req_type(ie, req_type) ||
332 wps_build_config_methods(ie, methods) ||
333 wps_build_uuid_e(ie, uuid) ||
334 wps_build_primary_dev_type(dev, ie) ||
335 wps_build_rf_bands(dev, ie) ||
336 wps_build_assoc_state(NULL, ie) ||
337 wps_build_config_error(ie, WPS_CFG_NO_ERROR) ||
338 wps_build_dev_password_id(ie, pbc ? DEV_PW_PUSHBUTTON :
344 *len = wpabuf_len(ie) - 2;
350 void wps_free_pending_msgs(struct upnp_pending_message *msgs)
352 struct upnp_pending_message *p, *prev;
357 wpabuf_free(prev->msg);
363 int wps_attr_text(struct wpabuf *data, char *buf, char *end)
365 struct wps_parse_attr attr;
369 if (wps_parse_msg(data, &attr) < 0)
372 if (attr.wps_state) {
373 if (*attr.wps_state == WPS_STATE_NOT_CONFIGURED)
374 ret = os_snprintf(pos, end - pos,
375 "wps_state=unconfigured\n");
376 else if (*attr.wps_state == WPS_STATE_CONFIGURED)
377 ret = os_snprintf(pos, end - pos,
378 "wps_state=configured\n");
381 if (ret < 0 || ret >= end - pos)
386 if (attr.ap_setup_locked && *attr.ap_setup_locked) {
387 ret = os_snprintf(pos, end - pos,
388 "wps_ap_setup_locked=1\n");
389 if (ret < 0 || ret >= end - pos)
394 if (attr.selected_registrar && *attr.selected_registrar) {
395 ret = os_snprintf(pos, end - pos,
396 "wps_selected_registrar=1\n");
397 if (ret < 0 || ret >= end - pos)
402 if (attr.dev_password_id) {
403 ret = os_snprintf(pos, end - pos,
404 "wps_device_password_id=%u\n",
405 WPA_GET_BE16(attr.dev_password_id));
406 if (ret < 0 || ret >= end - pos)
411 if (attr.sel_reg_config_methods) {
412 ret = os_snprintf(pos, end - pos,
413 "wps_selected_registrar_config_methods="
415 WPA_GET_BE16(attr.sel_reg_config_methods));
416 if (ret < 0 || ret >= end - pos)
421 if (attr.primary_dev_type) {
422 char devtype[WPS_DEV_TYPE_BUFSIZE];
423 ret = os_snprintf(pos, end - pos,
424 "wps_primary_device_type=%s\n",
425 wps_dev_type_bin2str(attr.primary_dev_type,
428 if (ret < 0 || ret >= end - pos)
434 char *str = os_malloc(attr.dev_name_len + 1);
438 for (i = 0; i < attr.dev_name_len; i++) {
439 if (attr.dev_name[i] < 32)
442 str[i] = attr.dev_name[i];
445 ret = os_snprintf(pos, end - pos, "wps_device_name=%s\n", str);
447 if (ret < 0 || ret >= end - pos)
452 if (attr.config_methods) {
453 ret = os_snprintf(pos, end - pos,
454 "wps_config_methods=0x%04x\n",
455 WPA_GET_BE16(attr.config_methods));
456 if (ret < 0 || ret >= end - pos)