wps_attr_parse.c revision 04949598a23f501be6eec21697465fd46a28840a
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Wi-Fi Protected Setup - attribute parsing
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
1204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "wps_defs.h"
1304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "wps_attr_parse.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_WPS_STRICT
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define WPS_WORKAROUNDS
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS_STRICT */
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr,
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  u8 id, u8 len, const u8 *pos)
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_EXCESSIVE, "WPS: WFA subelement id=%u len=%u",
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   id, len);
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (id) {
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WFA_ELEM_VERSION2:
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 1) {
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Version2 length "
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "%u", len);
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->version2 = pos;
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WFA_ELEM_AUTHORIZEDMACS:
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->authorized_macs = pos;
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->authorized_macs_len = len;
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WFA_ELEM_NETWORK_KEY_SHAREABLE:
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 1) {
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key "
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Shareable length %u", len);
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->network_key_shareable = pos;
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WFA_ELEM_REQUEST_TO_ENROLL:
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 1) {
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Request to Enroll "
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "length %u", len);
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->request_to_enroll = pos;
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WFA_ELEM_SETTINGS_DELAY_TIME:
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 1) {
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Settings Delay "
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Time length %u", len);
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->settings_delay_time = pos;
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_MSGDUMP, "WPS: Skipped unknown WFA Vendor "
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Extension subelement %u", id);
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wps_parse_vendor_ext_wfa(struct wps_parse_attr *attr, const u8 *pos,
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    u16 len)
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *end = pos + len;
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 id, elen;
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos + 2 < end) {
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		id = *pos++;
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		elen = *pos++;
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos + elen > end)
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wps_set_vendor_ext_wfa_subelem(attr, id, elen, pos) < 0)
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += elen;
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wps_parse_vendor_ext(struct wps_parse_attr *attr, const u8 *pos,
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				u16 len)
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u32 vendor_id;
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 3) {
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "WPS: Skip invalid Vendor Extension");
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	vendor_id = WPA_GET_BE24(pos);
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (vendor_id) {
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPS_VENDOR_ID_WFA:
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wps_parse_vendor_ext_wfa(attr, pos + 3, len - 3);
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Handle unknown vendor extensions */
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_MSGDUMP, "WPS: Unknown Vendor Extension (Vendor ID %u)",
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   vendor_id);
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > WPS_MAX_VENDOR_EXT_LEN) {
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "WPS: Too long Vendor Extension (%u)",
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   len);
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (attr->num_vendor_ext >= MAX_WPS_PARSE_VENDOR_EXT) {
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "WPS: Skipped Vendor Extension "
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "attribute (max %d vendor extensions)",
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   MAX_WPS_PARSE_VENDOR_EXT);
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	attr->vendor_ext[attr->num_vendor_ext] = pos;
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	attr->vendor_ext_len[attr->num_vendor_ext] = len;
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	attr->num_vendor_ext++;
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wps_set_attr(struct wps_parse_attr *attr, u16 type,
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const u8 *pos, u16 len)
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (type) {
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_VERSION:
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 1) {
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Version length %u",
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   len);
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->version = pos;
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_MSG_TYPE:
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 1) {
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type "
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "length %u", len);
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->msg_type = pos;
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_ENROLLEE_NONCE:
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != WPS_NONCE_LEN) {
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce "
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "length %u", len);
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->enrollee_nonce = pos;
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_REGISTRAR_NONCE:
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != WPS_NONCE_LEN) {
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce "
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "length %u", len);
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->registrar_nonce = pos;
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_UUID_E:
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != WPS_UUID_LEN) {
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-E length %u",
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   len);
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->uuid_e = pos;
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_UUID_R:
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != WPS_UUID_LEN) {
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-R length %u",
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   len);
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->uuid_r = pos;
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_AUTH_TYPE_FLAGS:
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 2) {
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Type Flags length %u", len);
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->auth_type_flags = pos;
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_ENCR_TYPE_FLAGS:
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 2) {
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption Type "
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Flags length %u", len);
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->encr_type_flags = pos;
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_CONN_TYPE_FLAGS:
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 1) {
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Connection Type "
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Flags length %u", len);
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->conn_type_flags = pos;
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_CONFIG_METHODS:
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 2) {
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Config Methods "
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "length %u", len);
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->config_methods = pos;
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_SELECTED_REGISTRAR_CONFIG_METHODS:
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 2) {
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Selected "
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Registrar Config Methods length %u", len);
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->sel_reg_config_methods = pos;
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_PRIMARY_DEV_TYPE:
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != WPS_DEV_TYPE_LEN) {
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Primary Device "
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Type length %u", len);
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->primary_dev_type = pos;
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_RF_BANDS:
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 1) {
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid RF Bands length "
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "%u", len);
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->rf_bands = pos;
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_ASSOC_STATE:
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 2) {
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Association State "
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "length %u", len);
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->assoc_state = pos;
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_CONFIG_ERROR:
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 2) {
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Configuration "
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Error length %u", len);
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->config_error = pos;
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_DEV_PASSWORD_ID:
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 2) {
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Device Password "
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "ID length %u", len);
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->dev_password_id = pos;
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_OOB_DEVICE_PASSWORD:
26604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (len < WPS_OOB_PUBKEY_HASH_LEN + 2 +
26704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		    WPS_OOB_DEVICE_PASSWORD_MIN_LEN ||
26804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		    len > WPS_OOB_PUBKEY_HASH_LEN + 2 +
26904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		    WPS_OOB_DEVICE_PASSWORD_LEN) {
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid OOB Device "
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Password length %u", len);
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->oob_dev_password = pos;
27504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		attr->oob_dev_password_len = len;
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_OS_VERSION:
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 4) {
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length "
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "%u", len);
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->os_version = pos;
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_WPS_STATE:
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 1) {
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Wi-Fi Protected "
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Setup State length %u", len);
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->wps_state = pos;
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_AUTHENTICATOR:
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != WPS_AUTHENTICATOR_LEN) {
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Authenticator "
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "length %u", len);
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->authenticator = pos;
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_R_HASH1:
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != WPS_HASH_LEN) {
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash1 length %u",
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   len);
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->r_hash1 = pos;
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_R_HASH2:
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != WPS_HASH_LEN) {
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash2 length %u",
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   len);
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->r_hash2 = pos;
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_E_HASH1:
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != WPS_HASH_LEN) {
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash1 length %u",
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   len);
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->e_hash1 = pos;
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_E_HASH2:
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != WPS_HASH_LEN) {
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash2 length %u",
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   len);
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->e_hash2 = pos;
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_R_SNONCE1:
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != WPS_SECRET_NONCE_LEN) {
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce1 length "
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "%u", len);
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->r_snonce1 = pos;
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_R_SNONCE2:
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != WPS_SECRET_NONCE_LEN) {
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce2 length "
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "%u", len);
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->r_snonce2 = pos;
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_E_SNONCE1:
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != WPS_SECRET_NONCE_LEN) {
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce1 length "
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "%u", len);
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->e_snonce1 = pos;
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_E_SNONCE2:
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != WPS_SECRET_NONCE_LEN) {
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce2 length "
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "%u", len);
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->e_snonce2 = pos;
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_KEY_WRAP_AUTH:
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != WPS_KWA_LEN) {
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Key Wrap "
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Authenticator length %u", len);
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->key_wrap_auth = pos;
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_AUTH_TYPE:
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 2) {
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Type length %u", len);
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->auth_type = pos;
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_ENCR_TYPE:
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 2) {
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption "
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Type length %u", len);
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->encr_type = pos;
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_NETWORK_INDEX:
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 1) {
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Network Index "
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "length %u", len);
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->network_idx = pos;
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_NETWORK_KEY_INDEX:
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 1) {
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key Index "
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "length %u", len);
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->network_key_idx = pos;
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_MAC_ADDR:
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != ETH_ALEN) {
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid MAC Address "
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "length %u", len);
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->mac_addr = pos;
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_KEY_PROVIDED_AUTO:
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 1) {
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Key Provided "
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Automatically length %u", len);
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->key_prov_auto = pos;
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_802_1X_ENABLED:
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 1) {
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid 802.1X Enabled "
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "length %u", len);
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->dot1x_enabled = pos;
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_SELECTED_REGISTRAR:
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 1) {
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Selected Registrar"
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   " length %u", len);
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->selected_registrar = pos;
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_REQUEST_TYPE:
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 1) {
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Request Type "
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "length %u", len);
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->request_type = pos;
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_RESPONSE_TYPE:
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 1) {
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Response Type "
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "length %u", len);
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->response_type = pos;
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_MANUFACTURER:
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->manufacturer = pos;
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->manufacturer_len = len;
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_MODEL_NAME:
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->model_name = pos;
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->model_name_len = len;
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_MODEL_NUMBER:
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->model_number = pos;
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->model_number_len = len;
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_SERIAL_NUMBER:
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->serial_number = pos;
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->serial_number_len = len;
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_DEV_NAME:
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->dev_name = pos;
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->dev_name_len = len;
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_PUBLIC_KEY:
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->public_key = pos;
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->public_key_len = len;
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_ENCR_SETTINGS:
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->encr_settings = pos;
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->encr_settings_len = len;
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_CRED:
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (attr->num_cred >= MAX_CRED_COUNT) {
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Skipped Credential "
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "attribute (max %d credentials)",
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   MAX_CRED_COUNT);
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->cred[attr->num_cred] = pos;
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->cred_len[attr->num_cred] = len;
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->num_cred++;
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_SSID:
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->ssid = pos;
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->ssid_len = len;
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_NETWORK_KEY:
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->network_key = pos;
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->network_key_len = len;
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_EAP_TYPE:
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->eap_type = pos;
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->eap_type_len = len;
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_EAP_IDENTITY:
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->eap_identity = pos;
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->eap_identity_len = len;
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_AP_SETUP_LOCKED:
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != 1) {
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid AP Setup Locked "
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "length %u", len);
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->ap_setup_locked = pos;
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_REQUESTED_DEV_TYPE:
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len != WPS_DEV_TYPE_LEN) {
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Requested Device "
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Type length %u", len);
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (attr->num_req_dev_type >= MAX_REQ_DEV_TYPE_COUNT) {
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Skipped Requested Device "
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Type attribute (max %u types)",
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   MAX_REQ_DEV_TYPE_COUNT);
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->req_dev_type[attr->num_req_dev_type] = pos;
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->num_req_dev_type++;
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_SECONDARY_DEV_TYPE_LIST:
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len > WPS_SEC_DEV_TYPE_MAX_LEN ||
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (len % WPS_DEV_TYPE_LEN) > 0) {
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid Secondary Device "
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Type length %u", len);
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->sec_dev_type_list = pos;
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		attr->sec_dev_type_list_len = len;
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ATTR_VENDOR_EXT:
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wps_parse_vendor_ext(attr, pos, len) < 0)
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x "
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "len=%u", type, len);
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr)
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end;
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 type, len;
5591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef WPS_WORKAROUNDS
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 prev_type = 0;
5611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* WPS_WORKAROUNDS */
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(attr, 0, sizeof(*attr));
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = wpabuf_head(msg);
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + wpabuf_len(msg);
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos < end) {
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (end - pos < 4) {
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Invalid message - "
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "%lu bytes remaining",
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (unsigned long) (end - pos));
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type = WPA_GET_BE16(pos);
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 2;
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = WPA_GET_BE16(pos);
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 2;
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_EXCESSIVE, "WPS: attr type=0x%x len=%u",
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   type, len);
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len > end - pos) {
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPS: Attribute overflow");
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump_buf(MSG_MSGDUMP, "WPS: Message data", msg);
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef WPS_WORKAROUNDS
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * Some deployed APs seem to have a bug in encoding of
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * Network Key attribute in the Credential attribute
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * where they add an extra octet after the Network Key
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * attribute at least when open network is being
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * provisioned.
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if ((type & 0xff00) != 0x1000 &&
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    prev_type == ATTR_NETWORK_KEY) {
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "WPS: Workaround - try "
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "to skip unexpected octet after "
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "Network Key");
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				pos -= 3;
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				continue;
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* WPS_WORKAROUNDS */
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef WPS_WORKAROUNDS
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (type == 0 && len == 0) {
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * Mac OS X 10.6 seems to be adding 0x00 padding to the
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * end of M1. Skip those to avoid interop issues.
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			int i;
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			for (i = 0; i < end - pos; i++) {
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				if (pos[i])
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					break;
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (i == end - pos) {
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "WPS: Workaround - skip "
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "unexpected message padding");
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* WPS_WORKAROUNDS */
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wps_set_attr(attr, type, pos, len) < 0)
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef WPS_WORKAROUNDS
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev_type = type;
6281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* WPS_WORKAROUNDS */
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += len;
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
634