2 * Wi-Fi Protected Setup - attribute parsing
3 * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
13 #include "wps_attr_parse.h"
15 #ifndef CONFIG_WPS_STRICT
16 #define WPS_WORKAROUNDS
17 #endif /* CONFIG_WPS_STRICT */
20 static int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr,
21 u8 id, u8 len, const u8 *pos)
23 wpa_printf(MSG_EXCESSIVE, "WPS: WFA subelement id=%u len=%u",
26 case WFA_ELEM_VERSION2:
28 wpa_printf(MSG_DEBUG, "WPS: Invalid Version2 length "
34 case WFA_ELEM_AUTHORIZEDMACS:
35 attr->authorized_macs = pos;
36 attr->authorized_macs_len = len;
38 case WFA_ELEM_NETWORK_KEY_SHAREABLE:
40 wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key "
41 "Shareable length %u", len);
44 attr->network_key_shareable = pos;
46 case WFA_ELEM_REQUEST_TO_ENROLL:
48 wpa_printf(MSG_DEBUG, "WPS: Invalid Request to Enroll "
52 attr->request_to_enroll = pos;
54 case WFA_ELEM_SETTINGS_DELAY_TIME:
56 wpa_printf(MSG_DEBUG, "WPS: Invalid Settings Delay "
57 "Time length %u", len);
60 attr->settings_delay_time = pos;
63 wpa_printf(MSG_MSGDUMP, "WPS: Skipped unknown WFA Vendor "
64 "Extension subelement %u", id);
72 static int wps_parse_vendor_ext_wfa(struct wps_parse_attr *attr, const u8 *pos,
75 const u8 *end = pos + len;
78 while (pos + 2 < end) {
83 if (wps_set_vendor_ext_wfa_subelem(attr, id, elen, pos) < 0)
92 static int wps_parse_vendor_ext(struct wps_parse_attr *attr, const u8 *pos,
98 wpa_printf(MSG_DEBUG, "WPS: Skip invalid Vendor Extension");
102 vendor_id = WPA_GET_BE24(pos);
104 case WPS_VENDOR_ID_WFA:
105 return wps_parse_vendor_ext_wfa(attr, pos + 3, len - 3);
108 /* Handle unknown vendor extensions */
110 wpa_printf(MSG_MSGDUMP, "WPS: Unknown Vendor Extension (Vendor ID %u)",
113 if (len > WPS_MAX_VENDOR_EXT_LEN) {
114 wpa_printf(MSG_DEBUG, "WPS: Too long Vendor Extension (%u)",
119 if (attr->num_vendor_ext >= MAX_WPS_PARSE_VENDOR_EXT) {
120 wpa_printf(MSG_DEBUG, "WPS: Skipped Vendor Extension "
121 "attribute (max %d vendor extensions)",
122 MAX_WPS_PARSE_VENDOR_EXT);
125 attr->vendor_ext[attr->num_vendor_ext] = pos;
126 attr->vendor_ext_len[attr->num_vendor_ext] = len;
127 attr->num_vendor_ext++;
133 static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
134 const u8 *pos, u16 len)
139 wpa_printf(MSG_DEBUG, "WPS: Invalid Version length %u",
147 wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type "
151 attr->msg_type = pos;
153 case ATTR_ENROLLEE_NONCE:
154 if (len != WPS_NONCE_LEN) {
155 wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce "
159 attr->enrollee_nonce = pos;
161 case ATTR_REGISTRAR_NONCE:
162 if (len != WPS_NONCE_LEN) {
163 wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce "
167 attr->registrar_nonce = pos;
170 if (len != WPS_UUID_LEN) {
171 wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-E length %u",
178 if (len != WPS_UUID_LEN) {
179 wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-R length %u",
185 case ATTR_AUTH_TYPE_FLAGS:
187 wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
188 "Type Flags length %u", len);
191 attr->auth_type_flags = pos;
193 case ATTR_ENCR_TYPE_FLAGS:
195 wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption Type "
196 "Flags length %u", len);
199 attr->encr_type_flags = pos;
201 case ATTR_CONN_TYPE_FLAGS:
203 wpa_printf(MSG_DEBUG, "WPS: Invalid Connection Type "
204 "Flags length %u", len);
207 attr->conn_type_flags = pos;
209 case ATTR_CONFIG_METHODS:
211 wpa_printf(MSG_DEBUG, "WPS: Invalid Config Methods "
215 attr->config_methods = pos;
217 case ATTR_SELECTED_REGISTRAR_CONFIG_METHODS:
219 wpa_printf(MSG_DEBUG, "WPS: Invalid Selected "
220 "Registrar Config Methods length %u", len);
223 attr->sel_reg_config_methods = pos;
225 case ATTR_PRIMARY_DEV_TYPE:
226 if (len != WPS_DEV_TYPE_LEN) {
227 wpa_printf(MSG_DEBUG, "WPS: Invalid Primary Device "
228 "Type length %u", len);
231 attr->primary_dev_type = pos;
235 wpa_printf(MSG_DEBUG, "WPS: Invalid RF Bands length "
239 attr->rf_bands = pos;
241 case ATTR_ASSOC_STATE:
243 wpa_printf(MSG_DEBUG, "WPS: Invalid Association State "
247 attr->assoc_state = pos;
249 case ATTR_CONFIG_ERROR:
251 wpa_printf(MSG_DEBUG, "WPS: Invalid Configuration "
252 "Error length %u", len);
255 attr->config_error = pos;
257 case ATTR_DEV_PASSWORD_ID:
259 wpa_printf(MSG_DEBUG, "WPS: Invalid Device Password "
260 "ID length %u", len);
263 attr->dev_password_id = pos;
265 case ATTR_OOB_DEVICE_PASSWORD:
266 if (len < WPS_OOB_PUBKEY_HASH_LEN + 2 ||
267 len > WPS_OOB_PUBKEY_HASH_LEN + 2 +
268 WPS_OOB_DEVICE_PASSWORD_LEN ||
269 (len < WPS_OOB_PUBKEY_HASH_LEN + 2 +
270 WPS_OOB_DEVICE_PASSWORD_MIN_LEN &&
271 WPA_GET_BE16(pos + WPS_OOB_PUBKEY_HASH_LEN) !=
272 DEV_PW_NFC_CONNECTION_HANDOVER)) {
273 wpa_printf(MSG_DEBUG, "WPS: Invalid OOB Device "
274 "Password length %u", len);
277 attr->oob_dev_password = pos;
278 attr->oob_dev_password_len = len;
280 case ATTR_OS_VERSION:
282 wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length "
286 attr->os_version = pos;
290 wpa_printf(MSG_DEBUG, "WPS: Invalid Wi-Fi Protected "
291 "Setup State length %u", len);
294 attr->wps_state = pos;
296 case ATTR_AUTHENTICATOR:
297 if (len != WPS_AUTHENTICATOR_LEN) {
298 wpa_printf(MSG_DEBUG, "WPS: Invalid Authenticator "
302 attr->authenticator = pos;
305 if (len != WPS_HASH_LEN) {
306 wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash1 length %u",
313 if (len != WPS_HASH_LEN) {
314 wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash2 length %u",
321 if (len != WPS_HASH_LEN) {
322 wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash1 length %u",
329 if (len != WPS_HASH_LEN) {
330 wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash2 length %u",
337 if (len != WPS_SECRET_NONCE_LEN) {
338 wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce1 length "
342 attr->r_snonce1 = pos;
345 if (len != WPS_SECRET_NONCE_LEN) {
346 wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce2 length "
350 attr->r_snonce2 = pos;
353 if (len != WPS_SECRET_NONCE_LEN) {
354 wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce1 length "
358 attr->e_snonce1 = pos;
361 if (len != WPS_SECRET_NONCE_LEN) {
362 wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce2 length "
366 attr->e_snonce2 = pos;
368 case ATTR_KEY_WRAP_AUTH:
369 if (len != WPS_KWA_LEN) {
370 wpa_printf(MSG_DEBUG, "WPS: Invalid Key Wrap "
371 "Authenticator length %u", len);
374 attr->key_wrap_auth = pos;
378 wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
379 "Type length %u", len);
382 attr->auth_type = pos;
386 wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption "
387 "Type length %u", len);
390 attr->encr_type = pos;
392 case ATTR_NETWORK_INDEX:
394 wpa_printf(MSG_DEBUG, "WPS: Invalid Network Index "
398 attr->network_idx = pos;
400 case ATTR_NETWORK_KEY_INDEX:
402 wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key Index "
406 attr->network_key_idx = pos;
409 if (len != ETH_ALEN) {
410 wpa_printf(MSG_DEBUG, "WPS: Invalid MAC Address "
414 attr->mac_addr = pos;
416 case ATTR_KEY_PROVIDED_AUTO:
418 wpa_printf(MSG_DEBUG, "WPS: Invalid Key Provided "
419 "Automatically length %u", len);
422 attr->key_prov_auto = pos;
424 case ATTR_802_1X_ENABLED:
426 wpa_printf(MSG_DEBUG, "WPS: Invalid 802.1X Enabled "
430 attr->dot1x_enabled = pos;
432 case ATTR_SELECTED_REGISTRAR:
434 wpa_printf(MSG_DEBUG, "WPS: Invalid Selected Registrar"
438 attr->selected_registrar = pos;
440 case ATTR_REQUEST_TYPE:
442 wpa_printf(MSG_DEBUG, "WPS: Invalid Request Type "
446 attr->request_type = pos;
448 case ATTR_RESPONSE_TYPE:
450 wpa_printf(MSG_DEBUG, "WPS: Invalid Response Type "
454 attr->response_type = pos;
456 case ATTR_MANUFACTURER:
457 attr->manufacturer = pos;
458 attr->manufacturer_len = len;
460 case ATTR_MODEL_NAME:
461 attr->model_name = pos;
462 attr->model_name_len = len;
464 case ATTR_MODEL_NUMBER:
465 attr->model_number = pos;
466 attr->model_number_len = len;
468 case ATTR_SERIAL_NUMBER:
469 attr->serial_number = pos;
470 attr->serial_number_len = len;
473 attr->dev_name = pos;
474 attr->dev_name_len = len;
476 case ATTR_PUBLIC_KEY:
477 attr->public_key = pos;
478 attr->public_key_len = len;
480 case ATTR_ENCR_SETTINGS:
481 attr->encr_settings = pos;
482 attr->encr_settings_len = len;
485 if (attr->num_cred >= MAX_CRED_COUNT) {
486 wpa_printf(MSG_DEBUG, "WPS: Skipped Credential "
487 "attribute (max %d credentials)",
491 attr->cred[attr->num_cred] = pos;
492 attr->cred_len[attr->num_cred] = len;
497 attr->ssid_len = len;
499 case ATTR_NETWORK_KEY:
500 attr->network_key = pos;
501 attr->network_key_len = len;
504 attr->eap_type = pos;
505 attr->eap_type_len = len;
507 case ATTR_EAP_IDENTITY:
508 attr->eap_identity = pos;
509 attr->eap_identity_len = len;
511 case ATTR_AP_SETUP_LOCKED:
513 wpa_printf(MSG_DEBUG, "WPS: Invalid AP Setup Locked "
517 attr->ap_setup_locked = pos;
519 case ATTR_REQUESTED_DEV_TYPE:
520 if (len != WPS_DEV_TYPE_LEN) {
521 wpa_printf(MSG_DEBUG, "WPS: Invalid Requested Device "
522 "Type length %u", len);
525 if (attr->num_req_dev_type >= MAX_REQ_DEV_TYPE_COUNT) {
526 wpa_printf(MSG_DEBUG, "WPS: Skipped Requested Device "
527 "Type attribute (max %u types)",
528 MAX_REQ_DEV_TYPE_COUNT);
531 attr->req_dev_type[attr->num_req_dev_type] = pos;
532 attr->num_req_dev_type++;
534 case ATTR_SECONDARY_DEV_TYPE_LIST:
535 if (len > WPS_SEC_DEV_TYPE_MAX_LEN ||
536 (len % WPS_DEV_TYPE_LEN) > 0) {
537 wpa_printf(MSG_DEBUG, "WPS: Invalid Secondary Device "
538 "Type length %u", len);
541 attr->sec_dev_type_list = pos;
542 attr->sec_dev_type_list_len = len;
544 case ATTR_VENDOR_EXT:
545 if (wps_parse_vendor_ext(attr, pos, len) < 0)
548 case ATTR_AP_CHANNEL:
550 wpa_printf(MSG_DEBUG, "WPS: Invalid AP Channel "
554 attr->ap_channel = pos;
557 wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x "
558 "len=%u", type, len);
566 int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr)
570 #ifdef WPS_WORKAROUNDS
572 #endif /* WPS_WORKAROUNDS */
574 os_memset(attr, 0, sizeof(*attr));
575 pos = wpabuf_head(msg);
576 end = pos + wpabuf_len(msg);
580 wpa_printf(MSG_DEBUG, "WPS: Invalid message - "
581 "%lu bytes remaining",
582 (unsigned long) (end - pos));
586 type = WPA_GET_BE16(pos);
588 len = WPA_GET_BE16(pos);
590 wpa_printf(MSG_EXCESSIVE, "WPS: attr type=0x%x len=%u",
592 if (len > end - pos) {
593 wpa_printf(MSG_DEBUG, "WPS: Attribute overflow");
594 wpa_hexdump_buf(MSG_MSGDUMP, "WPS: Message data", msg);
595 #ifdef WPS_WORKAROUNDS
597 * Some deployed APs seem to have a bug in encoding of
598 * Network Key attribute in the Credential attribute
599 * where they add an extra octet after the Network Key
600 * attribute at least when open network is being
603 if ((type & 0xff00) != 0x1000 &&
604 prev_type == ATTR_NETWORK_KEY) {
605 wpa_printf(MSG_DEBUG, "WPS: Workaround - try "
606 "to skip unexpected octet after "
611 #endif /* WPS_WORKAROUNDS */
615 #ifdef WPS_WORKAROUNDS
616 if (type == 0 && len == 0) {
618 * Mac OS X 10.6 seems to be adding 0x00 padding to the
619 * end of M1. Skip those to avoid interop issues.
622 for (i = 0; i < end - pos; i++) {
626 if (i == end - pos) {
627 wpa_printf(MSG_DEBUG, "WPS: Workaround - skip "
628 "unexpected message padding");
632 #endif /* WPS_WORKAROUNDS */
634 if (wps_set_attr(attr, type, pos, len) < 0)
637 #ifdef WPS_WORKAROUNDS
639 #endif /* WPS_WORKAROUNDS */