wps_attr_parse.c revision a38abf9af7bec7e89dbfb39ac7bb77223fe47c72
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/*
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Wi-Fi Protected Setup - attribute parsing
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * This software may be distributed under the terms of the BSD license.
67dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * See README for more details.
77dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch */
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "includes.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "common.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "wps_defs.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "wps_attr_parse.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef CONFIG_WPS_STRICT
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#define WPS_WORKAROUNDS
177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#endif /* CONFIG_WPS_STRICT */
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstatic int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr,
2123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)					  u8 id, u8 len, const u8 *pos)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	wpa_printf(MSG_EXCESSIVE, "WPS: WFA subelement id=%u len=%u",
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		   id, len);
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	switch (id) {
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	case WFA_ELEM_VERSION2:
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (len != 1) {
287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			wpa_printf(MSG_DEBUG, "WPS: Invalid Version2 length "
297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch				   "%u", len);
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			return -1;
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		}
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		attr->version2 = pos;
337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		break;
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	case WFA_ELEM_AUTHORIZEDMACS:
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		attr->authorized_macs = pos;
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		attr->authorized_macs_len = len;
377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		break;
38010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	case WFA_ELEM_NETWORK_KEY_SHAREABLE:
39010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		if (len != 1) {
40010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key "
41010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)				   "Shareable length %u", len);
42010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)			return -1;
43010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		}
44010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		attr->network_key_shareable = pos;
45010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		break;
46010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	case WFA_ELEM_REQUEST_TO_ENROLL:
477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		if (len != 1) {
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid Request to Enroll "
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   "length %u", len);
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			return -1;
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		}
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->request_to_enroll = pos;
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case WFA_ELEM_SETTINGS_DELAY_TIME:
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (len != 1) {
567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			wpa_printf(MSG_DEBUG, "WPS: Invalid Settings Delay "
577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch				   "Time length %u", len);
587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			return -1;
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		}
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->settings_delay_time = pos;
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS:
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (len != 2) {
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Configuration Methods length %u",
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   len);
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			return -1;
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		}
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->registrar_configuration_methods = pos;
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	default:
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		wpa_printf(MSG_MSGDUMP, "WPS: Skipped unknown WFA Vendor "
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			   "Extension subelement %u", id);
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	}
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	return 0;
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static int wps_parse_vendor_ext_wfa(struct wps_parse_attr *attr, const u8 *pos,
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				    u16 len)
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles){
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	const u8 *end = pos + len;
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	u8 id, elen;
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	while (pos + 2 <= end) {
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		id = *pos++;
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		elen = *pos++;
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (pos + elen > end)
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			break;
91e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch		if (wps_set_vendor_ext_wfa_subelem(attr, id, elen, pos) < 0)
92e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch			return -1;
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		pos += elen;
94e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch	}
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	return 0;
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static int wps_parse_vendor_ext(struct wps_parse_attr *attr, const u8 *pos,
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				u16 len)
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles){
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	u32 vendor_id;
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	if (len < 3) {
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		wpa_printf(MSG_DEBUG, "WPS: Skip invalid Vendor Extension");
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		return 0;
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	}
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
110e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch	vendor_id = WPA_GET_BE24(pos);
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	switch (vendor_id) {
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case WPS_VENDOR_ID_WFA:
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		return wps_parse_vendor_ext_wfa(attr, pos + 3, len - 3);
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	}
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	/* Handle unknown vendor extensions */
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	wpa_printf(MSG_MSGDUMP, "WPS: Unknown Vendor Extension (Vendor ID %u)",
119e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch		   vendor_id);
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	if (len > WPS_MAX_VENDOR_EXT_LEN) {
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		wpa_printf(MSG_DEBUG, "WPS: Too long Vendor Extension (%u)",
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			   len);
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		return -1;
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	}
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	if (attr->num_vendor_ext >= MAX_WPS_PARSE_VENDOR_EXT) {
128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		wpa_printf(MSG_DEBUG, "WPS: Skipped Vendor Extension "
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			   "attribute (max %d vendor extensions)",
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			   MAX_WPS_PARSE_VENDOR_EXT);
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		return -1;
132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	}
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	attr->vendor_ext[attr->num_vendor_ext] = pos;
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	attr->vendor_ext_len[attr->num_vendor_ext] = len;
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	attr->num_vendor_ext++;
13623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
137effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch	return 0;
13823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
141010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			const u8 *pos, u16 len)
143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles){
144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	switch (type) {
145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_VERSION:
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (len != 1) {
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid Version length %u",
148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				   len);
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			return -1;
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		}
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		attr->version = pos;
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		break;
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	case ATTR_MSG_TYPE:
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (len != 1) {
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type "
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   "length %u", len);
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			return -1;
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		}
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		attr->msg_type = pos;
1607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		break;
161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_ENROLLEE_NONCE:
162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (len != WPS_NONCE_LEN) {
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce "
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   "length %u", len);
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			return -1;
1667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		}
1677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		attr->enrollee_nonce = pos;
168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_REGISTRAR_NONCE:
170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (len != WPS_NONCE_LEN) {
171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce "
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   "length %u", len);
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			return -1;
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		}
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		attr->registrar_nonce = pos;
1767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		break;
177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_UUID_E:
178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (len != WPS_UUID_LEN) {
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-E length %u",
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   len);
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			return -1;
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		}
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		attr->uuid_e = pos;
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		break;
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	case ATTR_UUID_R:
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (len != WPS_UUID_LEN) {
1877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-R length %u",
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   len);
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			return -1;
1907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		}
191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->uuid_r = pos;
192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	case ATTR_AUTH_TYPE_FLAGS:
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (len != 2) {
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   "Type Flags length %u", len);
1977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			return -1;
1987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		}
1997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		attr->auth_type_flags = pos;
200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		break;
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	case ATTR_ENCR_TYPE_FLAGS:
202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (len != 2) {
203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption Type "
204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				   "Flags length %u", len);
205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			return -1;
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		}
2077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		attr->encr_type_flags = pos;
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		break;
209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	case ATTR_CONN_TYPE_FLAGS:
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (len != 1) {
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid Connection Type "
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   "Flags length %u", len);
213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			return -1;
214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		}
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		attr->conn_type_flags = pos;
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		break;
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	case ATTR_CONFIG_METHODS:
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (len != 2) {
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid Config Methods "
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   "length %u", len);
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			return -1;
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		}
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		attr->config_methods = pos;
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		break;
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	case ATTR_SELECTED_REGISTRAR_CONFIG_METHODS:
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (len != 2) {
2277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			wpa_printf(MSG_DEBUG, "WPS: Invalid Selected "
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   "Registrar Config Methods length %u", len);
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			return -1;
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		}
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		attr->sel_reg_config_methods = pos;
2327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		break;
2337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	case ATTR_PRIMARY_DEV_TYPE:
2347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		if (len != WPS_DEV_TYPE_LEN) {
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid Primary Device "
236a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				   "Type length %u", len);
237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			return -1;
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		}
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		attr->primary_dev_type = pos;
240a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	case ATTR_RF_BANDS:
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (len != 1) {
243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid RF Bands length "
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   "%u", len);
245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			return -1;
246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		}
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		attr->rf_bands = pos;
248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		break;
249010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	case ATTR_ASSOC_STATE:
250010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		if (len != 2) {
2517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			wpa_printf(MSG_DEBUG, "WPS: Invalid Association State "
2527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch				   "length %u", len);
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			return -1;
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		}
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->assoc_state = pos;
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	case ATTR_CONFIG_ERROR:
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (len != 2) {
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid Configuration "
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   "Error length %u", len);
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			return -1;
2627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		}
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		attr->config_error = pos;
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		break;
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	case ATTR_DEV_PASSWORD_ID:
2667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		if (len != 2) {
2677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			wpa_printf(MSG_DEBUG, "WPS: Invalid Device Password "
2687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch				   "ID length %u", len);
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			return -1;
270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		}
271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->dev_password_id = pos;
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		break;
273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_OOB_DEVICE_PASSWORD:
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (len < WPS_OOB_PUBKEY_HASH_LEN + 2 ||
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		    len > WPS_OOB_PUBKEY_HASH_LEN + 2 +
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		    WPS_OOB_DEVICE_PASSWORD_LEN ||
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		    (len < WPS_OOB_PUBKEY_HASH_LEN + 2 +
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		     WPS_OOB_DEVICE_PASSWORD_MIN_LEN &&
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		     WPA_GET_BE16(pos + WPS_OOB_PUBKEY_HASH_LEN) !=
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		     DEV_PW_NFC_CONNECTION_HANDOVER)) {
281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			wpa_printf(MSG_DEBUG, "WPS: Invalid OOB Device "
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   "Password length %u", len);
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			return -1;
2847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		}
285a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->oob_dev_password = pos;
286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->oob_dev_password_len = len;
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		break;
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	case ATTR_OS_VERSION:
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (len != 4) {
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length "
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   "%u", len);
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			return -1;
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		}
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		attr->os_version = pos;
2957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		break;
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	case ATTR_WPS_STATE:
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (len != 1) {
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid Wi-Fi Protected "
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   "Setup State length %u", len);
3007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			return -1;
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		}
302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		attr->wps_state = pos;
303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_AUTHENTICATOR:
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (len != WPS_AUTHENTICATOR_LEN) {
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid Authenticator "
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   "length %u", len);
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			return -1;
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		}
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		attr->authenticator = pos;
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		break;
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	case ATTR_R_HASH1:
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (len != WPS_HASH_LEN) {
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash1 length %u",
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   len);
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			return -1;
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		}
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		attr->r_hash1 = pos;
3197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		break;
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	case ATTR_R_HASH2:
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (len != WPS_HASH_LEN) {
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash2 length %u",
3237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch				   len);
324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			return -1;
3257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		}
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		attr->r_hash2 = pos;
3277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		break;
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	case ATTR_E_HASH1:
329a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (len != WPS_HASH_LEN) {
330a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash1 length %u",
331a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				   len);
332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			return -1;
333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		}
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		attr->e_hash1 = pos;
3350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch		break;
3367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	case ATTR_E_HASH2:
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (len != WPS_HASH_LEN) {
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash2 length %u",
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   len);
340a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			return -1;
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		}
342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		attr->e_hash2 = pos;
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		break;
344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	case ATTR_R_SNONCE1:
345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if (len != WPS_SECRET_NONCE_LEN) {
346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce1 length "
347a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				   "%u", len);
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			return -1;
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		}
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		attr->r_snonce1 = pos;
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		break;
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	case ATTR_R_SNONCE2:
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (len != WPS_SECRET_NONCE_LEN) {
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce2 length "
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   "%u", len);
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			return -1;
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		}
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		attr->r_snonce2 = pos;
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		break;
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	case ATTR_E_SNONCE1:
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (len != WPS_SECRET_NONCE_LEN) {
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce1 length "
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   "%u", len);
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			return -1;
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		}
3667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		attr->e_snonce1 = pos;
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		break;
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	case ATTR_E_SNONCE2:
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (len != WPS_SECRET_NONCE_LEN) {
3707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce2 length "
3717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch				   "%u", len);
372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			return -1;
3737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		}
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		attr->e_snonce2 = pos;
3757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		break;
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	case ATTR_KEY_WRAP_AUTH:
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (len != WPS_KWA_LEN) {
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid Key Wrap "
379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch				   "Authenticator length %u", len);
3807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			return -1;
3817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		}
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		attr->key_wrap_auth = pos;
383a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
384a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_AUTH_TYPE:
385a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (len != 2) {
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
387a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				   "Type length %u", len);
388a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			return -1;
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		}
390a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->auth_type = pos;
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		break;
392a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_ENCR_TYPE:
393a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (len != 2) {
394a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption "
395a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				   "Type length %u", len);
396a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			return -1;
397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		}
398a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->encr_type = pos;
399a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
400a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_NETWORK_INDEX:
401a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (len != 1) {
402a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid Network Index "
403a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				   "length %u", len);
404a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			return -1;
405a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		}
406a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->network_idx = pos;
407a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
408a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_NETWORK_KEY_INDEX:
409a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (len != 1) {
410a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key Index "
411a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				   "length %u", len);
412a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			return -1;
413a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		}
414a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->network_key_idx = pos;
415a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
416a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_MAC_ADDR:
417a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (len != ETH_ALEN) {
418a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid MAC Address "
419a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				   "length %u", len);
420a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			return -1;
421a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		}
422a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->mac_addr = pos;
423a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
424a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_SELECTED_REGISTRAR:
425a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (len != 1) {
426a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid Selected Registrar"
427a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				   " length %u", len);
428a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			return -1;
429a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		}
430a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->selected_registrar = pos;
431a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
432a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_REQUEST_TYPE:
4330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch		if (len != 1) {
4340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch			wpa_printf(MSG_DEBUG, "WPS: Invalid Request Type "
435a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				   "length %u", len);
4360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch			return -1;
437a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		}
438a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->request_type = pos;
439a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
440a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_RESPONSE_TYPE:
441a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (len != 1) {
442a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid Response Type "
443a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				   "length %u", len);
444a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			return -1;
445a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		}
446010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		attr->response_type = pos;
447a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
448a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_MANUFACTURER:
449a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->manufacturer = pos;
450a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->manufacturer_len = len;
451a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
452a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_MODEL_NAME:
453e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch		attr->model_name = pos;
454a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->model_name_len = len;
455e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch		break;
456a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_MODEL_NUMBER:
457a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->model_number = pos;
458a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->model_number_len = len;
459a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
460a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_SERIAL_NUMBER:
461a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->serial_number = pos;
462a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->serial_number_len = len;
463a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
464a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_DEV_NAME:
465a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->dev_name = pos;
466a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->dev_name_len = len;
467a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
468a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_PUBLIC_KEY:
469a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->public_key = pos;
470a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->public_key_len = len;
471a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
472a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_ENCR_SETTINGS:
473a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->encr_settings = pos;
474a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->encr_settings_len = len;
475a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
476a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_CRED:
477a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (attr->num_cred >= MAX_CRED_COUNT) {
478a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Skipped Credential "
479a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				   "attribute (max %d credentials)",
480a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				   MAX_CRED_COUNT);
481a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			break;
482a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		}
483a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->cred[attr->num_cred] = pos;
484a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->cred_len[attr->num_cred] = len;
485a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->num_cred++;
486a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
487a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_SSID:
488a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->ssid = pos;
489a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->ssid_len = len;
490a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
491a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_NETWORK_KEY:
492a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->network_key = pos;
493a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->network_key_len = len;
494a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
495a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_AP_SETUP_LOCKED:
496a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (len != 1) {
497a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid AP Setup Locked "
498a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				   "length %u", len);
499a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			return -1;
500a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		}
501a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->ap_setup_locked = pos;
502a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
503a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_REQUESTED_DEV_TYPE:
504a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (len != WPS_DEV_TYPE_LEN) {
505a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid Requested Device "
506a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				   "Type length %u", len);
507a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			return -1;
508a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		}
509a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (attr->num_req_dev_type >= MAX_REQ_DEV_TYPE_COUNT) {
5100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch			wpa_printf(MSG_DEBUG, "WPS: Skipped Requested Device "
511a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				   "Type attribute (max %u types)",
512a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				   MAX_REQ_DEV_TYPE_COUNT);
513a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			break;
514a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		}
515a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->req_dev_type[attr->num_req_dev_type] = pos;
516a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->num_req_dev_type++;
517a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
518a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_SECONDARY_DEV_TYPE_LIST:
519a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (len > WPS_SEC_DEV_TYPE_MAX_LEN ||
520a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		    (len % WPS_DEV_TYPE_LEN) > 0) {
521a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid Secondary Device "
522e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch				   "Type length %u", len);
523a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			return -1;
524e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch		}
525a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->sec_dev_type_list = pos;
526a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->sec_dev_type_list_len = len;
527a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
528a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_VENDOR_EXT:
529a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (wps_parse_vendor_ext(attr, pos, len) < 0)
530a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			return -1;
531a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
532a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	case ATTR_AP_CHANNEL:
533a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (len != 2) {
534a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid AP Channel "
535a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				   "length %u", len);
536a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			return -1;
537a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		}
538a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		attr->ap_channel = pos;
539a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
540a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	default:
541a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x "
542a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			   "len=%u", type, len);
543a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
544a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	}
545a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
546a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	return 0;
547a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
548a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
549a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
550a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr)
551a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles){
552a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	const u8 *pos, *end;
553a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	u16 type, len;
554a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#ifdef WPS_WORKAROUNDS
555a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	u16 prev_type = 0;
556a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif /* WPS_WORKAROUNDS */
557a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
558a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	os_memset(attr, 0, sizeof(*attr));
559a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	pos = wpabuf_head(msg);
560a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	end = pos + wpabuf_len(msg);
561a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
562a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	while (pos < end) {
563a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (end - pos < 4) {
564a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Invalid message - "
565a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				   "%lu bytes remaining",
566a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				   (unsigned long) (end - pos));
567a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			return -1;
568a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		}
5690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
5700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch		type = WPA_GET_BE16(pos);
571a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		pos += 2;
572a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		len = WPA_GET_BE16(pos);
573a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		pos += 2;
574a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		wpa_printf(MSG_EXCESSIVE, "WPS: attr type=0x%x len=%u",
575a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			   type, len);
576a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (len > end - pos) {
577a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			wpa_printf(MSG_DEBUG, "WPS: Attribute overflow");
578a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			wpa_hexdump_buf(MSG_MSGDUMP, "WPS: Message data", msg);
579a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#ifdef WPS_WORKAROUNDS
580a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			/*
581e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch			 * Some deployed APs seem to have a bug in encoding of
582a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			 * Network Key attribute in the Credential attribute
583e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch			 * where they add an extra octet after the Network Key
584a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			 * attribute at least when open network is being
585a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			 * provisioned.
586a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			 */
587a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			if ((type & 0xff00) != 0x1000 &&
588a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			    prev_type == ATTR_NETWORK_KEY) {
589a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				wpa_printf(MSG_DEBUG, "WPS: Workaround - try "
590a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)					   "to skip unexpected octet after "
591a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)					   "Network Key");
592a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				pos -= 3;
593a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				continue;
594a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			}
595a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif /* WPS_WORKAROUNDS */
596a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			return -1;
597a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		}
598a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifdef WPS_WORKAROUNDS
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (type == 0 && len == 0) {
601effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch			/*
602effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch			 * Mac OS X 10.6 seems to be adding 0x00 padding to the
603effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch			 * end of M1. Skip those to avoid interop issues.
604effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch			 */
605effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch			int i;
606effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch			for (i = 0; i < end - pos; i++) {
607effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch				if (pos[i])
608effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch					break;
609effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch			}
610effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch			if (i == end - pos) {
611effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch				wpa_printf(MSG_DEBUG, "WPS: Workaround - skip "
612effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch					   "unexpected message padding");
613effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch				break;
614effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch			}
615effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch		}
616effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#endif /* WPS_WORKAROUNDS */
617effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
618effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch		if (wps_set_attr(attr, type, pos, len) < 0)
619e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch			return -1;
620e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
621010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#ifdef WPS_WORKAROUNDS
622010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		prev_type = type;
623010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif /* WPS_WORKAROUNDS */
624010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		pos += len;
625effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch	}
626effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
627010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	return 0;
628effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
629effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch