1 /* 2 * Wi-Fi Protected Setup 3 * Copyright (c) 2007-2009, 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 "crypto/dh_group5.h" 19 #include "common/ieee802_11_defs.h" 20 #include "wps_i.h" 21 #include "wps_dev_attr.h" 22 23 24 /** 25 * wps_init - Initialize WPS Registration protocol data 26 * @cfg: WPS configuration 27 * Returns: Pointer to allocated data or %NULL on failure 28 * 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(). 33 */ 34 struct wps_data * wps_init(const struct wps_config *cfg) 35 { 36 struct wps_data *data = os_zalloc(sizeof(*data)); 37 if (data == NULL) 38 return NULL; 39 data->wps = cfg->wps; 40 data->registrar = cfg->registrar; 41 if (cfg->registrar) { 42 os_memcpy(data->uuid_r, cfg->wps->uuid, WPS_UUID_LEN); 43 } else { 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); 46 } 47 if (cfg->pin) { 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) { 52 os_free(data); 53 return NULL; 54 } 55 os_memcpy(data->dev_password, cfg->pin, cfg->pin_len); 56 data->dev_password_len = cfg->pin_len; 57 } 58 59 data->pbc = cfg->pbc; 60 if (cfg->pbc) { 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) { 66 os_free(data); 67 return NULL; 68 } 69 os_memset(data->dev_password, '0', 8); 70 data->dev_password_len = 8; 71 } 72 73 data->state = data->registrar ? RECV_M1 : SEND_M1; 74 75 if (cfg->assoc_wps_ie) { 76 struct wps_parse_attr attr; 77 wpa_hexdump_buf(MSG_DEBUG, "WPS: WPS IE from (Re)AssocReq", 78 cfg->assoc_wps_ie); 79 if (wps_parse_msg(cfg->assoc_wps_ie, &attr) < 0) { 80 wpa_printf(MSG_DEBUG, "WPS: Failed to parse WPS IE " 81 "from (Re)AssocReq"); 82 } else if (attr.request_type == NULL) { 83 wpa_printf(MSG_DEBUG, "WPS: No Request Type attribute " 84 "in (Re)AssocReq WPS IE"); 85 } else { 86 wpa_printf(MSG_DEBUG, "WPS: Request Type (from WPS IE " 87 "in (Re)AssocReq WPS IE): %d", 88 *attr.request_type); 89 data->request_type = *attr.request_type; 90 } 91 } 92 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) { 97 os_free(data); 98 return NULL; 99 } 100 os_memcpy(data->new_ap_settings, cfg->new_ap_settings, 101 sizeof(*data->new_ap_settings)); 102 } 103 104 if (cfg->peer_addr) 105 os_memcpy(data->peer_dev.mac_addr, cfg->peer_addr, ETH_ALEN); 106 107 data->use_psk_key = cfg->use_psk_key; 108 109 return data; 110 } 111 112 113 /** 114 * wps_deinit - Deinitialize WPS Registration protocol data 115 * @data: WPS Registration protocol data from wps_init() 116 */ 117 void wps_deinit(struct wps_data *data) 118 { 119 if (data->wps_pin_revealed) { 120 wpa_printf(MSG_DEBUG, "WPS: Full PIN information revealed and " 121 "negotiation failed"); 122 if (data->registrar) 123 wps_registrar_invalidate_pin(data->wps->registrar, 124 data->uuid_e); 125 } else if (data->registrar) 126 wps_registrar_unlock_pin(data->wps->registrar, data->uuid_e); 127 128 wpabuf_free(data->dh_privkey); 129 wpabuf_free(data->dh_pubkey_e); 130 wpabuf_free(data->dh_pubkey_r); 131 wpabuf_free(data->last_msg); 132 os_free(data->dev_password); 133 os_free(data->new_psk); 134 wps_device_data_free(&data->peer_dev); 135 os_free(data->new_ap_settings); 136 dh5_free(data->dh_ctx); 137 os_free(data); 138 } 139 140 141 /** 142 * wps_process_msg - Process a WPS message 143 * @wps: WPS Registration protocol data from wps_init() 144 * @op_code: Message OP Code 145 * @msg: Message data 146 * Returns: Processing result 147 * 148 * This function is used to process WPS messages with OP Codes WSC_ACK, 149 * WSC_NACK, WSC_MSG, and WSC_Done. The caller (e.g., EAP server/peer) is 150 * responsible for reassembling the messages before calling this function. 151 * Response to this message is built by calling wps_get_msg(). 152 */ 153 enum wps_process_res wps_process_msg(struct wps_data *wps, 154 enum wsc_op_code op_code, 155 const struct wpabuf *msg) 156 { 157 if (wps->registrar) 158 return wps_registrar_process_msg(wps, op_code, msg); 159 else 160 return wps_enrollee_process_msg(wps, op_code, msg); 161 } 162 163 164 /** 165 * wps_get_msg - Build a WPS message 166 * @wps: WPS Registration protocol data from wps_init() 167 * @op_code: Buffer for returning message OP Code 168 * Returns: The generated WPS message or %NULL on failure 169 * 170 * This function is used to build a response to a message processed by calling 171 * wps_process_msg(). The caller is responsible for freeing the buffer. 172 */ 173 struct wpabuf * wps_get_msg(struct wps_data *wps, enum wsc_op_code *op_code) 174 { 175 if (wps->registrar) 176 return wps_registrar_get_msg(wps, op_code); 177 else 178 return wps_enrollee_get_msg(wps, op_code); 179 } 180 181 182 /** 183 * wps_is_selected_pbc_registrar - Check whether WPS IE indicates active PBC 184 * @msg: WPS IE contents from Beacon or Probe Response frame 185 * Returns: 1 if PBC Registrar is active, 0 if not 186 */ 187 int wps_is_selected_pbc_registrar(const struct wpabuf *msg) 188 { 189 struct wps_parse_attr attr; 190 191 /* 192 * In theory, this could also verify that attr.sel_reg_config_methods 193 * includes WPS_CONFIG_PUSHBUTTON, but some deployed AP implementations 194 * do not set Selected Registrar Config Methods attribute properly, so 195 * it is safer to just use Device Password ID here. 196 */ 197 198 if (wps_parse_msg(msg, &attr) < 0 || 199 !attr.selected_registrar || *attr.selected_registrar == 0 || 200 !attr.dev_password_id || 201 WPA_GET_BE16(attr.dev_password_id) != DEV_PW_PUSHBUTTON) 202 return 0; 203 204 return 1; 205 } 206 207 208 /** 209 * wps_is_selected_pin_registrar - Check whether WPS IE indicates active PIN 210 * @msg: WPS IE contents from Beacon or Probe Response frame 211 * Returns: 1 if PIN Registrar is active, 0 if not 212 */ 213 int wps_is_selected_pin_registrar(const struct wpabuf *msg) 214 { 215 struct wps_parse_attr attr; 216 217 /* 218 * In theory, this could also verify that attr.sel_reg_config_methods 219 * includes WPS_CONFIG_LABEL, WPS_CONFIG_DISPLAY, or WPS_CONFIG_KEYPAD, 220 * but some deployed AP implementations do not set Selected Registrar 221 * Config Methods attribute properly, so it is safer to just use 222 * Device Password ID here. 223 */ 224 225 if (wps_parse_msg(msg, &attr) < 0) 226 return 0; 227 228 if (!attr.selected_registrar || *attr.selected_registrar == 0) 229 return 0; 230 231 if (attr.dev_password_id != NULL && 232 WPA_GET_BE16(attr.dev_password_id) == DEV_PW_PUSHBUTTON) 233 return 0; 234 235 return 1; 236 } 237 238 239 /** 240 * wps_get_uuid_e - Get UUID-E from WPS IE 241 * @msg: WPS IE contents from Beacon or Probe Response frame 242 * Returns: Pointer to UUID-E or %NULL if not included 243 * 244 * The returned pointer is to the msg contents and it remains valid only as 245 * long as the msg buffer is valid. 246 */ 247 const u8 * wps_get_uuid_e(const struct wpabuf *msg) 248 { 249 struct wps_parse_attr attr; 250 251 if (wps_parse_msg(msg, &attr) < 0) 252 return NULL; 253 return attr.uuid_e; 254 } 255 256 257 /** 258 * wps_build_assoc_req_ie - Build WPS IE for (Re)Association Request 259 * @req_type: Value for Request Type attribute 260 * Returns: WPS IE or %NULL on failure 261 * 262 * The caller is responsible for freeing the buffer. 263 */ 264 struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type) 265 { 266 struct wpabuf *ie; 267 u8 *len; 268 269 wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for (Re)Association " 270 "Request"); 271 ie = wpabuf_alloc(100); 272 if (ie == NULL) 273 return NULL; 274 275 wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); 276 len = wpabuf_put(ie, 1); 277 wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); 278 279 if (wps_build_version(ie) || 280 wps_build_req_type(ie, req_type)) { 281 wpabuf_free(ie); 282 return NULL; 283 } 284 285 *len = wpabuf_len(ie) - 2; 286 287 return ie; 288 } 289 290 291 /** 292 * wps_build_assoc_resp_ie - Build WPS IE for (Re)Association Response 293 * Returns: WPS IE or %NULL on failure 294 * 295 * The caller is responsible for freeing the buffer. 296 */ 297 struct wpabuf * wps_build_assoc_resp_ie(void) 298 { 299 struct wpabuf *ie; 300 u8 *len; 301 302 wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for (Re)Association " 303 "Response"); 304 ie = wpabuf_alloc(100); 305 if (ie == NULL) 306 return NULL; 307 308 wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); 309 len = wpabuf_put(ie, 1); 310 wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); 311 312 if (wps_build_version(ie) || 313 wps_build_resp_type(ie, WPS_RESP_AP)) { 314 wpabuf_free(ie); 315 return NULL; 316 } 317 318 *len = wpabuf_len(ie) - 2; 319 320 return ie; 321 } 322 323 324 /** 325 * wps_build_probe_req_ie - Build WPS IE for Probe Request 326 * @pbc: Whether searching for PBC mode APs 327 * @dev: Device attributes 328 * @uuid: Own UUID 329 * @req_type: Value for Request Type attribute 330 * Returns: WPS IE or %NULL on failure 331 * 332 * The caller is responsible for freeing the buffer. 333 */ 334 struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev, 335 const u8 *uuid, 336 enum wps_request_type req_type) 337 { 338 struct wpabuf *ie; 339 u8 *len; 340 u16 methods; 341 342 wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for Probe Request"); 343 344 ie = wpabuf_alloc(200); 345 if (ie == NULL) 346 return NULL; 347 348 wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); 349 len = wpabuf_put(ie, 1); 350 wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); 351 352 if (pbc) 353 methods = WPS_CONFIG_PUSHBUTTON; 354 else { 355 methods = WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY | 356 WPS_CONFIG_KEYPAD; 357 #ifdef CONFIG_WPS_UFD 358 methods |= WPS_CONFIG_USBA; 359 #endif /* CONFIG_WPS_UFD */ 360 #ifdef CONFIG_WPS_NFC 361 methods |= WPS_CONFIG_NFC_INTERFACE; 362 #endif /* CONFIG_WPS_NFC */ 363 } 364 365 if (wps_build_version(ie) || 366 wps_build_req_type(ie, req_type) || 367 wps_build_config_methods(ie, methods) || 368 wps_build_uuid_e(ie, uuid) || 369 wps_build_primary_dev_type(dev, ie) || 370 wps_build_rf_bands(dev, ie) || 371 wps_build_assoc_state(NULL, ie) || 372 wps_build_config_error(ie, WPS_CFG_NO_ERROR) || 373 wps_build_dev_password_id(ie, pbc ? DEV_PW_PUSHBUTTON : 374 DEV_PW_DEFAULT)) { 375 wpabuf_free(ie); 376 return NULL; 377 } 378 379 *len = wpabuf_len(ie) - 2; 380 381 return ie; 382 } 383 384 385 void wps_free_pending_msgs(struct upnp_pending_message *msgs) 386 { 387 struct upnp_pending_message *p, *prev; 388 p = msgs; 389 while (p) { 390 prev = p; 391 p = p->next; 392 wpabuf_free(prev->msg); 393 os_free(prev); 394 } 395 } 396 397 398 int wps_attr_text(struct wpabuf *data, char *buf, char *end) 399 { 400 struct wps_parse_attr attr; 401 char *pos = buf; 402 int ret; 403 404 if (wps_parse_msg(data, &attr) < 0) 405 return -1; 406 407 if (attr.wps_state) { 408 if (*attr.wps_state == WPS_STATE_NOT_CONFIGURED) 409 ret = os_snprintf(pos, end - pos, 410 "wps_state=unconfigured\n"); 411 else if (*attr.wps_state == WPS_STATE_CONFIGURED) 412 ret = os_snprintf(pos, end - pos, 413 "wps_state=configured\n"); 414 else 415 ret = 0; 416 if (ret < 0 || ret >= end - pos) 417 return pos - buf; 418 pos += ret; 419 } 420 421 if (attr.ap_setup_locked && *attr.ap_setup_locked) { 422 ret = os_snprintf(pos, end - pos, 423 "wps_ap_setup_locked=1\n"); 424 if (ret < 0 || ret >= end - pos) 425 return pos - buf; 426 pos += ret; 427 } 428 429 if (attr.selected_registrar && *attr.selected_registrar) { 430 ret = os_snprintf(pos, end - pos, 431 "wps_selected_registrar=1\n"); 432 if (ret < 0 || ret >= end - pos) 433 return pos - buf; 434 pos += ret; 435 } 436 437 if (attr.dev_password_id) { 438 ret = os_snprintf(pos, end - pos, 439 "wps_device_password_id=%u\n", 440 WPA_GET_BE16(attr.dev_password_id)); 441 if (ret < 0 || ret >= end - pos) 442 return pos - buf; 443 pos += ret; 444 } 445 446 if (attr.sel_reg_config_methods) { 447 ret = os_snprintf(pos, end - pos, 448 "wps_selected_registrar_config_methods=" 449 "0x%04x\n", 450 WPA_GET_BE16(attr.sel_reg_config_methods)); 451 if (ret < 0 || ret >= end - pos) 452 return pos - buf; 453 pos += ret; 454 } 455 456 if (attr.primary_dev_type) { 457 char devtype[WPS_DEV_TYPE_BUFSIZE]; 458 ret = os_snprintf(pos, end - pos, 459 "wps_primary_device_type=%s\n", 460 wps_dev_type_bin2str(attr.primary_dev_type, 461 devtype, 462 sizeof(devtype))); 463 if (ret < 0 || ret >= end - pos) 464 return pos - buf; 465 pos += ret; 466 } 467 468 if (attr.dev_name) { 469 char *str = os_malloc(attr.dev_name_len + 1); 470 size_t i; 471 if (str == NULL) 472 return pos - buf; 473 for (i = 0; i < attr.dev_name_len; i++) { 474 if (attr.dev_name[i] < 32) 475 str[i] = '_'; 476 else 477 str[i] = attr.dev_name[i]; 478 } 479 str[i] = '\0'; 480 ret = os_snprintf(pos, end - pos, "wps_device_name=%s\n", str); 481 os_free(str); 482 if (ret < 0 || ret >= end - pos) 483 return pos - buf; 484 pos += ret; 485 } 486 487 if (attr.config_methods) { 488 ret = os_snprintf(pos, end - pos, 489 "wps_config_methods=0x%04x\n", 490 WPA_GET_BE16(attr.config_methods)); 491 if (ret < 0 || ret >= end - pos) 492 return pos - buf; 493 pos += ret; 494 } 495 496 return pos - buf; 497 } 498