2 * Wi-Fi Protected Setup - attribute parsing
3 * Copyright (c) 2008, 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.
20 #ifndef CONFIG_WPS_STRICT
21 #define WPS_WORKAROUNDS
22 #endif /* CONFIG_WPS_STRICT */
25 static int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr,
26 u8 id, u8 len, const u8 *pos)
28 wpa_printf(MSG_EXCESSIVE, "WPS: WFA subelement id=%u len=%u",
31 case WFA_ELEM_VERSION2:
33 wpa_printf(MSG_DEBUG, "WPS: Invalid Version2 length "
39 case WFA_ELEM_AUTHORIZEDMACS:
40 attr->authorized_macs = pos;
41 attr->authorized_macs_len = len;
43 case WFA_ELEM_NETWORK_KEY_SHAREABLE:
45 wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key "
46 "Shareable length %u", len);
49 attr->network_key_shareable = pos;
51 case WFA_ELEM_REQUEST_TO_ENROLL:
53 wpa_printf(MSG_DEBUG, "WPS: Invalid Request to Enroll "
57 attr->request_to_enroll = pos;
59 case WFA_ELEM_SETTINGS_DELAY_TIME:
61 wpa_printf(MSG_DEBUG, "WPS: Invalid Settings Delay "
62 "Time length %u", len);
65 attr->settings_delay_time = pos;
68 wpa_printf(MSG_MSGDUMP, "WPS: Skipped unknown WFA Vendor "
69 "Extension subelement %u", id);
77 static int wps_parse_vendor_ext_wfa(struct wps_parse_attr *attr, const u8 *pos,
80 const u8 *end = pos + len;
83 while (pos + 2 < end) {
88 if (wps_set_vendor_ext_wfa_subelem(attr, id, elen, pos) < 0)
97 static int wps_parse_vendor_ext(struct wps_parse_attr *attr, const u8 *pos,
103 wpa_printf(MSG_DEBUG, "WPS: Skip invalid Vendor Extension");
107 vendor_id = WPA_GET_BE24(pos);
109 case WPS_VENDOR_ID_WFA:
110 return wps_parse_vendor_ext_wfa(attr, pos + 3, len - 3);
112 wpa_printf(MSG_MSGDUMP, "WPS: Skip unknown Vendor Extension "
113 "(Vendor ID %u)", vendor_id);
121 static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
122 const u8 *pos, u16 len)
127 wpa_printf(MSG_DEBUG, "WPS: Invalid Version length %u",
135 wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type "
139 attr->msg_type = pos;
141 case ATTR_ENROLLEE_NONCE:
142 if (len != WPS_NONCE_LEN) {
143 wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce "
147 attr->enrollee_nonce = pos;
149 case ATTR_REGISTRAR_NONCE:
150 if (len != WPS_NONCE_LEN) {
151 wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce "
155 attr->registrar_nonce = pos;
158 if (len != WPS_UUID_LEN) {
159 wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-E length %u",
166 if (len != WPS_UUID_LEN) {
167 wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-R length %u",
173 case ATTR_AUTH_TYPE_FLAGS:
175 wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
176 "Type Flags length %u", len);
179 attr->auth_type_flags = pos;
181 case ATTR_ENCR_TYPE_FLAGS:
183 wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption Type "
184 "Flags length %u", len);
187 attr->encr_type_flags = pos;
189 case ATTR_CONN_TYPE_FLAGS:
191 wpa_printf(MSG_DEBUG, "WPS: Invalid Connection Type "
192 "Flags length %u", len);
195 attr->conn_type_flags = pos;
197 case ATTR_CONFIG_METHODS:
199 wpa_printf(MSG_DEBUG, "WPS: Invalid Config Methods "
203 attr->config_methods = pos;
205 case ATTR_SELECTED_REGISTRAR_CONFIG_METHODS:
207 wpa_printf(MSG_DEBUG, "WPS: Invalid Selected "
208 "Registrar Config Methods length %u", len);
211 attr->sel_reg_config_methods = pos;
213 case ATTR_PRIMARY_DEV_TYPE:
214 if (len != WPS_DEV_TYPE_LEN) {
215 wpa_printf(MSG_DEBUG, "WPS: Invalid Primary Device "
216 "Type length %u", len);
219 attr->primary_dev_type = pos;
223 wpa_printf(MSG_DEBUG, "WPS: Invalid RF Bands length "
227 attr->rf_bands = pos;
229 case ATTR_ASSOC_STATE:
231 wpa_printf(MSG_DEBUG, "WPS: Invalid Association State "
235 attr->assoc_state = pos;
237 case ATTR_CONFIG_ERROR:
239 wpa_printf(MSG_DEBUG, "WPS: Invalid Configuration "
240 "Error length %u", len);
243 attr->config_error = pos;
245 case ATTR_DEV_PASSWORD_ID:
247 wpa_printf(MSG_DEBUG, "WPS: Invalid Device Password "
248 "ID length %u", len);
251 attr->dev_password_id = pos;
253 case ATTR_OOB_DEVICE_PASSWORD:
254 if (len != WPS_OOB_DEVICE_PASSWORD_ATTR_LEN) {
255 wpa_printf(MSG_DEBUG, "WPS: Invalid OOB Device "
256 "Password length %u", len);
259 attr->oob_dev_password = pos;
261 case ATTR_OS_VERSION:
263 wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length "
267 attr->os_version = pos;
271 wpa_printf(MSG_DEBUG, "WPS: Invalid Wi-Fi Protected "
272 "Setup State length %u", len);
275 attr->wps_state = pos;
277 case ATTR_AUTHENTICATOR:
278 if (len != WPS_AUTHENTICATOR_LEN) {
279 wpa_printf(MSG_DEBUG, "WPS: Invalid Authenticator "
283 attr->authenticator = pos;
286 if (len != WPS_HASH_LEN) {
287 wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash1 length %u",
294 if (len != WPS_HASH_LEN) {
295 wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash2 length %u",
302 if (len != WPS_HASH_LEN) {
303 wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash1 length %u",
310 if (len != WPS_HASH_LEN) {
311 wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash2 length %u",
318 if (len != WPS_SECRET_NONCE_LEN) {
319 wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce1 length "
323 attr->r_snonce1 = pos;
326 if (len != WPS_SECRET_NONCE_LEN) {
327 wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce2 length "
331 attr->r_snonce2 = pos;
334 if (len != WPS_SECRET_NONCE_LEN) {
335 wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce1 length "
339 attr->e_snonce1 = pos;
342 if (len != WPS_SECRET_NONCE_LEN) {
343 wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce2 length "
347 attr->e_snonce2 = pos;
349 case ATTR_KEY_WRAP_AUTH:
350 if (len != WPS_KWA_LEN) {
351 wpa_printf(MSG_DEBUG, "WPS: Invalid Key Wrap "
352 "Authenticator length %u", len);
355 attr->key_wrap_auth = pos;
359 wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
360 "Type length %u", len);
363 attr->auth_type = pos;
367 wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption "
368 "Type length %u", len);
371 attr->encr_type = pos;
373 case ATTR_NETWORK_INDEX:
375 wpa_printf(MSG_DEBUG, "WPS: Invalid Network Index "
379 attr->network_idx = pos;
381 case ATTR_NETWORK_KEY_INDEX:
383 wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key Index "
387 attr->network_key_idx = pos;
390 if (len != ETH_ALEN) {
391 wpa_printf(MSG_DEBUG, "WPS: Invalid MAC Address "
395 attr->mac_addr = pos;
397 case ATTR_KEY_PROVIDED_AUTO:
399 wpa_printf(MSG_DEBUG, "WPS: Invalid Key Provided "
400 "Automatically length %u", len);
403 attr->key_prov_auto = pos;
405 case ATTR_802_1X_ENABLED:
407 wpa_printf(MSG_DEBUG, "WPS: Invalid 802.1X Enabled "
411 attr->dot1x_enabled = pos;
413 case ATTR_SELECTED_REGISTRAR:
415 wpa_printf(MSG_DEBUG, "WPS: Invalid Selected Registrar"
419 attr->selected_registrar = pos;
421 case ATTR_REQUEST_TYPE:
423 wpa_printf(MSG_DEBUG, "WPS: Invalid Request Type "
427 attr->request_type = pos;
429 case ATTR_RESPONSE_TYPE:
431 wpa_printf(MSG_DEBUG, "WPS: Invalid Response Type "
435 attr->response_type = pos;
437 case ATTR_MANUFACTURER:
438 attr->manufacturer = pos;
439 attr->manufacturer_len = len;
441 case ATTR_MODEL_NAME:
442 attr->model_name = pos;
443 attr->model_name_len = len;
445 case ATTR_MODEL_NUMBER:
446 attr->model_number = pos;
447 attr->model_number_len = len;
449 case ATTR_SERIAL_NUMBER:
450 attr->serial_number = pos;
451 attr->serial_number_len = len;
454 attr->dev_name = pos;
455 attr->dev_name_len = len;
457 case ATTR_PUBLIC_KEY:
458 attr->public_key = pos;
459 attr->public_key_len = len;
461 case ATTR_ENCR_SETTINGS:
462 attr->encr_settings = pos;
463 attr->encr_settings_len = len;
466 if (attr->num_cred >= MAX_CRED_COUNT) {
467 wpa_printf(MSG_DEBUG, "WPS: Skipped Credential "
468 "attribute (max %d credentials)",
472 attr->cred[attr->num_cred] = pos;
473 attr->cred_len[attr->num_cred] = len;
478 attr->ssid_len = len;
480 case ATTR_NETWORK_KEY:
481 attr->network_key = pos;
482 attr->network_key_len = len;
485 attr->eap_type = pos;
486 attr->eap_type_len = len;
488 case ATTR_EAP_IDENTITY:
489 attr->eap_identity = pos;
490 attr->eap_identity_len = len;
492 case ATTR_AP_SETUP_LOCKED:
494 wpa_printf(MSG_DEBUG, "WPS: Invalid AP Setup Locked "
498 attr->ap_setup_locked = pos;
500 case ATTR_REQUESTED_DEV_TYPE:
501 if (len != WPS_DEV_TYPE_LEN) {
502 wpa_printf(MSG_DEBUG, "WPS: Invalid Requested Device "
503 "Type length %u", len);
506 if (attr->num_req_dev_type >= MAX_REQ_DEV_TYPE_COUNT) {
507 wpa_printf(MSG_DEBUG, "WPS: Skipped Requested Device "
508 "Type attribute (max %u types)",
509 MAX_REQ_DEV_TYPE_COUNT);
512 attr->req_dev_type[attr->num_req_dev_type] = pos;
513 attr->num_req_dev_type++;
515 case ATTR_VENDOR_EXT:
516 if (wps_parse_vendor_ext(attr, pos, len) < 0)
520 wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x "
521 "len=%u", type, len);
529 int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr)
535 os_memset(attr, 0, sizeof(*attr));
536 pos = wpabuf_head(msg);
537 end = pos + wpabuf_len(msg);
541 wpa_printf(MSG_DEBUG, "WPS: Invalid message - "
542 "%lu bytes remaining",
543 (unsigned long) (end - pos));
547 type = WPA_GET_BE16(pos);
549 len = WPA_GET_BE16(pos);
551 wpa_printf(MSG_EXCESSIVE, "WPS: attr type=0x%x len=%u",
553 if (len > end - pos) {
554 wpa_printf(MSG_DEBUG, "WPS: Attribute overflow");
555 wpa_hexdump_buf(MSG_MSGDUMP, "WPS: Message data", msg);
556 #ifdef WPS_WORKAROUNDS
558 * Some deployed APs seem to have a bug in encoding of
559 * Network Key attribute in the Credential attribute
560 * where they add an extra octet after the Network Key
561 * attribute at least when open network is being
564 if ((type & 0xff00) != 0x1000 &&
565 prev_type == ATTR_NETWORK_KEY) {
566 wpa_printf(MSG_DEBUG, "WPS: Workaround - try "
567 "to skip unexpected octet after "
572 #endif /* WPS_WORKAROUNDS */
576 #ifdef WPS_WORKAROUNDS
577 if (type == 0 && len == 0) {
579 * Mac OS X 10.6 seems to be adding 0x00 padding to the
580 * end of M1. Skip those to avoid interop issues.
583 for (i = 0; i < end - pos; i++) {
587 if (i == end - pos) {
588 wpa_printf(MSG_DEBUG, "WPS: Workaround - skip "
589 "unexpected message padding");
593 #endif /* WPS_WORKAROUNDS */
595 if (wps_set_attr(attr, type, pos, len) < 0)