1 /*
2  * Wi-Fi Protected Setup - device attributes
3  * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 #include "utils/includes.h"
9 #include "utils/common.h"
10 
11 #include "wps/wps_i.h"
12 #include "wps/wps_dev_attr.h"
13 
wps_build_manufacturer(struct wps_device_data * dev,struct wpabuf * msg)14 int wps_build_manufacturer(struct wps_device_data *dev, struct wpabuf *msg)
15 {
16 	size_t len;
17 	wpa_printf(MSG_DEBUG,  "WPS:  * Manufacturer");
18 	wpabuf_put_be16(msg, ATTR_MANUFACTURER);
19 	len = dev->manufacturer ? os_strlen(dev->manufacturer) : 0;
20 #ifndef CONFIG_WPS_STRICT
21 	if (len == 0) {
22 		/*
23 		 * Some deployed WPS implementations fail to parse zero-length
24 		 * attributes. As a workaround, send a space character if the
25 		 * device attribute string is empty.
26 		 */
27 		wpabuf_put_be16(msg, 1);
28 		wpabuf_put_u8(msg, ' ');
29 		return 0;
30 	}
31 #endif /* CONFIG_WPS_STRICT */
32 	wpabuf_put_be16(msg, len);
33 	wpabuf_put_data(msg, dev->manufacturer, len);
34 	return 0;
35 }
36 
37 
wps_build_model_name(struct wps_device_data * dev,struct wpabuf * msg)38 int wps_build_model_name(struct wps_device_data *dev, struct wpabuf *msg)
39 {
40 	size_t len;
41 	wpa_printf(MSG_DEBUG,  "WPS:  * Model Name");
42 	wpabuf_put_be16(msg, ATTR_MODEL_NAME);
43 	len = dev->model_name ? os_strlen(dev->model_name) : 0;
44 #ifndef CONFIG_WPS_STRICT
45 	if (len == 0) {
46 		/*
47 		 * Some deployed WPS implementations fail to parse zero-length
48 		 * attributes. As a workaround, send a space character if the
49 		 * device attribute string is empty.
50 		 */
51 		wpabuf_put_be16(msg, 1);
52 		wpabuf_put_u8(msg, ' ');
53 		return 0;
54 	}
55 #endif /* CONFIG_WPS_STRICT */
56 	wpabuf_put_be16(msg, len);
57 	wpabuf_put_data(msg, dev->model_name, len);
58 	return 0;
59 }
60 
61 
wps_build_model_number(struct wps_device_data * dev,struct wpabuf * msg)62 int wps_build_model_number(struct wps_device_data *dev, struct wpabuf *msg)
63 {
64 	size_t len;
65 	wpa_printf(MSG_DEBUG,  "WPS:  * Model Number");
66 	wpabuf_put_be16(msg, ATTR_MODEL_NUMBER);
67 	len = dev->model_number ? os_strlen(dev->model_number) : 0;
68 #ifndef CONFIG_WPS_STRICT
69 	if (len == 0) {
70 		/*
71 		 * Some deployed WPS implementations fail to parse zero-length
72 		 * attributes. As a workaround, send a space character if the
73 		 * device attribute string is empty.
74 		 */
75 		wpabuf_put_be16(msg, 1);
76 		wpabuf_put_u8(msg, ' ');
77 		return 0;
78 	}
79 #endif /* CONFIG_WPS_STRICT */
80 	wpabuf_put_be16(msg, len);
81 	wpabuf_put_data(msg, dev->model_number, len);
82 	return 0;
83 }
84 
85 
wps_build_serial_number(struct wps_device_data * dev,struct wpabuf * msg)86 static int wps_build_serial_number(struct wps_device_data *dev,
87 				   struct wpabuf *msg)
88 {
89 	size_t len;
90 	wpa_printf(MSG_DEBUG,  "WPS:  * Serial Number");
91 	wpabuf_put_be16(msg, ATTR_SERIAL_NUMBER);
92 	len = dev->serial_number ? os_strlen(dev->serial_number) : 0;
93 #ifndef CONFIG_WPS_STRICT
94 	if (len == 0) {
95 		/*
96 		 * Some deployed WPS implementations fail to parse zero-length
97 		 * attributes. As a workaround, send a space character if the
98 		 * device attribute string is empty.
99 		 */
100 		wpabuf_put_be16(msg, 1);
101 		wpabuf_put_u8(msg, ' ');
102 		return 0;
103 	}
104 #endif /* CONFIG_WPS_STRICT */
105 	wpabuf_put_be16(msg, len);
106 	wpabuf_put_data(msg, dev->serial_number, len);
107 	return 0;
108 }
109 
110 
wps_build_primary_dev_type(struct wps_device_data * dev,struct wpabuf * msg)111 int wps_build_primary_dev_type(struct wps_device_data *dev, struct wpabuf *msg)
112 {
113 	wpa_printf(MSG_DEBUG,  "WPS:  * Primary Device Type");
114 	wpabuf_put_be16(msg, ATTR_PRIMARY_DEV_TYPE);
115 	wpabuf_put_be16(msg, WPS_DEV_TYPE_LEN);
116 	wpabuf_put_data(msg, dev->pri_dev_type, WPS_DEV_TYPE_LEN);
117 	return 0;
118 }
119 
120 
wps_build_secondary_dev_type(struct wps_device_data * dev,struct wpabuf * msg)121 int wps_build_secondary_dev_type(struct wps_device_data *dev,
122 				  struct wpabuf *msg)
123 {
124 	if (!dev->num_sec_dev_types)
125 		return 0;
126 
127 	wpa_printf(MSG_DEBUG,  "WPS:  * Secondary Device Type");
128 	wpabuf_put_be16(msg, ATTR_SECONDARY_DEV_TYPE_LIST);
129 	wpabuf_put_be16(msg, WPS_DEV_TYPE_LEN * dev->num_sec_dev_types);
130 	wpabuf_put_data(msg, dev->sec_dev_type,
131 			WPS_DEV_TYPE_LEN * dev->num_sec_dev_types);
132 
133 	return 0;
134 }
135 
136 
wps_build_req_dev_type(struct wps_device_data * dev,struct wpabuf * msg,unsigned int num_req_dev_types,const u8 * req_dev_types)137 int wps_build_req_dev_type(struct wps_device_data *dev, struct wpabuf *msg,
138 			   unsigned int num_req_dev_types,
139 			   const u8 *req_dev_types)
140 {
141 	unsigned int i;
142 
143 	for (i = 0; i < num_req_dev_types; i++) {
144 		wpa_hexdump(MSG_DEBUG, "WPS: * Requested Device Type",
145 			    req_dev_types + i * WPS_DEV_TYPE_LEN,
146 			    WPS_DEV_TYPE_LEN);
147 		wpabuf_put_be16(msg, ATTR_REQUESTED_DEV_TYPE);
148 		wpabuf_put_be16(msg, WPS_DEV_TYPE_LEN);
149 		wpabuf_put_data(msg, req_dev_types + i * WPS_DEV_TYPE_LEN,
150 				WPS_DEV_TYPE_LEN);
151 	}
152 
153 	return 0;
154 }
155 
156 
wps_build_dev_name(struct wps_device_data * dev,struct wpabuf * msg)157 int wps_build_dev_name(struct wps_device_data *dev, struct wpabuf *msg)
158 {
159 	size_t len;
160 	wpa_printf(MSG_DEBUG,  "WPS:  * Device Name");
161 	wpabuf_put_be16(msg, ATTR_DEV_NAME);
162 	len = dev->device_name ? os_strlen(dev->device_name) : 0;
163 #ifndef CONFIG_WPS_STRICT
164 	if (len == 0) {
165 		/*
166 		 * Some deployed WPS implementations fail to parse zero-length
167 		 * attributes. As a workaround, send a space character if the
168 		 * device attribute string is empty.
169 		 */
170 		wpabuf_put_be16(msg, 1);
171 		wpabuf_put_u8(msg, ' ');
172 		return 0;
173 	}
174 #endif /* CONFIG_WPS_STRICT */
175 	wpabuf_put_be16(msg, len);
176 	wpabuf_put_data(msg, dev->device_name, len);
177 	return 0;
178 }
179 
180 
wps_build_device_attrs(struct wps_device_data * dev,struct wpabuf * msg)181 int wps_build_device_attrs(struct wps_device_data *dev, struct wpabuf *msg)
182 {
183 	if (wps_build_manufacturer(dev, msg) ||
184 	    wps_build_model_name(dev, msg) ||
185 	    wps_build_model_number(dev, msg) ||
186 	    wps_build_serial_number(dev, msg) ||
187 	    wps_build_primary_dev_type(dev, msg) ||
188 	    wps_build_dev_name(dev, msg))
189 		return -1;
190 	return 0;
191 }
192 
193 
wps_build_os_version(struct wps_device_data * dev,struct wpabuf * msg)194 int wps_build_os_version(struct wps_device_data *dev, struct wpabuf *msg)
195 {
196 	wpa_printf(MSG_DEBUG,  "WPS:  * OS Version");
197 	wpabuf_put_be16(msg, ATTR_OS_VERSION);
198 	wpabuf_put_be16(msg, 4);
199 	wpabuf_put_be32(msg, 0x80000000 | dev->os_version);
200 	return 0;
201 }
202 
203 
wps_build_vendor_ext_m1(struct wps_device_data * dev,struct wpabuf * msg)204 int wps_build_vendor_ext_m1(struct wps_device_data *dev, struct wpabuf *msg)
205 {
206 	if (dev->vendor_ext_m1 != NULL) {
207 		wpa_hexdump(MSG_DEBUG, "WPS:  * Vendor Extension M1",
208 			    wpabuf_head_u8(dev->vendor_ext_m1),
209 			    wpabuf_len(dev->vendor_ext_m1));
210 		wpabuf_put_be16(msg, ATTR_VENDOR_EXT);
211 		wpabuf_put_be16(msg, wpabuf_len(dev->vendor_ext_m1));
212 		wpabuf_put_buf(msg, dev->vendor_ext_m1);
213 	}
214 	return 0;
215 }
216 
217 
wps_build_rf_bands(struct wps_device_data * dev,struct wpabuf * msg)218 int wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg)
219 {
220 	wpa_printf(MSG_DEBUG,  "WPS:  * RF Bands (%x)", dev->rf_bands);
221 	wpabuf_put_be16(msg, ATTR_RF_BANDS);
222 	wpabuf_put_be16(msg, 1);
223 	wpabuf_put_u8(msg, dev->rf_bands);
224 	return 0;
225 }
226 
227 
wps_build_vendor_ext(struct wps_device_data * dev,struct wpabuf * msg)228 int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg)
229 {
230 	int i;
231 
232 	for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
233 		if (dev->vendor_ext[i] == NULL)
234 			continue;
235 		wpa_hexdump(MSG_DEBUG, "WPS:  * Vendor Extension",
236 			    wpabuf_head_u8(dev->vendor_ext[i]),
237 			    wpabuf_len(dev->vendor_ext[i]));
238 		wpabuf_put_be16(msg, ATTR_VENDOR_EXT);
239 		wpabuf_put_be16(msg, wpabuf_len(dev->vendor_ext[i]));
240 		wpabuf_put_buf(msg, dev->vendor_ext[i]);
241 	}
242 
243 	return 0;
244 }
245 
246 
wps_process_manufacturer(struct wps_device_data * dev,const u8 * str,size_t str_len)247 static int wps_process_manufacturer(struct wps_device_data *dev, const u8 *str,
248 				    size_t str_len)
249 {
250 	if (str == NULL) {
251 		wpa_printf(MSG_DEBUG,  "WPS: No Manufacturer received");
252 		return -1;
253 	}
254 
255 	wpa_hexdump_ascii(MSG_DEBUG, "WPS: Manufacturer", str, str_len);
256 
257 	os_free(dev->manufacturer);
258 	dev->manufacturer = (char *)os_malloc(str_len + 1);
259 	if (dev->manufacturer == NULL)
260 		return -1;
261 	os_memcpy(dev->manufacturer, str, str_len);
262 	dev->manufacturer[str_len] = '\0';
263 
264 	return 0;
265 }
266 
267 
wps_process_model_name(struct wps_device_data * dev,const u8 * str,size_t str_len)268 static int wps_process_model_name(struct wps_device_data *dev, const u8 *str,
269 				  size_t str_len)
270 {
271 	if (str == NULL) {
272 		wpa_printf(MSG_DEBUG,  "WPS: No Model Name received");
273 		return -1;
274 	}
275 
276 	wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Name", str, str_len);
277 
278 	os_free(dev->model_name);
279 	dev->model_name = (char *)os_malloc(str_len + 1);
280 	if (dev->model_name == NULL)
281 		return -1;
282 	os_memcpy(dev->model_name, str, str_len);
283 	dev->model_name[str_len] = '\0';
284 
285 	return 0;
286 }
287 
288 
wps_process_model_number(struct wps_device_data * dev,const u8 * str,size_t str_len)289 static int wps_process_model_number(struct wps_device_data *dev, const u8 *str,
290 				    size_t str_len)
291 {
292 	if (str == NULL) {
293 		wpa_printf(MSG_DEBUG,  "WPS: No Model Number received");
294 		return -1;
295 	}
296 
297 	wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Number", str, str_len);
298 
299 	os_free(dev->model_number);
300 	dev->model_number = (char *)os_malloc(str_len + 1);
301 	if (dev->model_number == NULL)
302 		return -1;
303 	os_memcpy(dev->model_number, str, str_len);
304 	dev->model_number[str_len] = '\0';
305 
306 	return 0;
307 }
308 
309 
wps_process_serial_number(struct wps_device_data * dev,const u8 * str,size_t str_len)310 static int wps_process_serial_number(struct wps_device_data *dev,
311 				     const u8 *str, size_t str_len)
312 {
313 	if (str == NULL) {
314 		wpa_printf(MSG_DEBUG,  "WPS: No Serial Number received");
315 		return -1;
316 	}
317 
318 	wpa_hexdump_ascii(MSG_DEBUG, "WPS: Serial Number", str, str_len);
319 
320 	os_free(dev->serial_number);
321 	dev->serial_number = (char *)os_malloc(str_len + 1);
322 	if (dev->serial_number == NULL)
323 		return -1;
324 	os_memcpy(dev->serial_number, str, str_len);
325 	dev->serial_number[str_len] = '\0';
326 
327 	return 0;
328 }
329 
330 
wps_process_dev_name(struct wps_device_data * dev,const u8 * str,size_t str_len)331 static int wps_process_dev_name(struct wps_device_data *dev, const u8 *str,
332 				size_t str_len)
333 {
334 	if (str == NULL) {
335 		wpa_printf(MSG_DEBUG,  "WPS: No Device Name received");
336 		return -1;
337 	}
338 
339 	wpa_hexdump_ascii(MSG_DEBUG, "WPS: Device Name", str, str_len);
340 
341 	os_free(dev->device_name);
342 	dev->device_name = (char *)os_malloc(str_len + 1);
343 	if (dev->device_name == NULL)
344 		return -1;
345 	os_memcpy(dev->device_name, str, str_len);
346 	dev->device_name[str_len] = '\0';
347 
348 	return 0;
349 }
350 
351 
wps_process_primary_dev_type(struct wps_device_data * dev,const u8 * dev_type)352 static int wps_process_primary_dev_type(struct wps_device_data *dev,
353 					const u8 *dev_type)
354 {
355 	if (dev_type == NULL) {
356 		wpa_printf(MSG_DEBUG,  "WPS: No Primary Device Type received");
357 		return -1;
358 	}
359 
360 	os_memcpy(dev->pri_dev_type, dev_type, WPS_DEV_TYPE_LEN);
361 
362 	return 0;
363 }
364 
365 
wps_process_device_attrs(struct wps_device_data * dev,struct wps_parse_attr * attr)366 int wps_process_device_attrs(struct wps_device_data *dev,
367 			     struct wps_parse_attr *attr)
368 {
369 	if (wps_process_manufacturer(dev, attr->manufacturer,
370 				     attr->manufacturer_len) ||
371 	    wps_process_model_name(dev, attr->model_name,
372 				   attr->model_name_len) ||
373 	    wps_process_model_number(dev, attr->model_number,
374 				     attr->model_number_len) ||
375 	    wps_process_serial_number(dev, attr->serial_number,
376 				      attr->serial_number_len) ||
377 	    wps_process_primary_dev_type(dev, attr->primary_dev_type) ||
378 	    wps_process_dev_name(dev, attr->dev_name, attr->dev_name_len))
379 		return -1;
380 	return 0;
381 }
382 
383 
wps_process_os_version(struct wps_device_data * dev,const u8 * ver)384 int wps_process_os_version(struct wps_device_data *dev, const u8 *ver)
385 {
386 	if (ver == NULL) {
387 		wpa_printf(MSG_DEBUG,  "WPS: No OS Version received");
388 		return -1;
389 	}
390 
391 	dev->os_version = WPA_GET_BE32(ver);
392 	wpa_printf(MSG_DEBUG,  "WPS: OS Version %08x", dev->os_version);
393 
394 	return 0;
395 }
396 
397 
wps_process_rf_bands(struct wps_device_data * dev,const u8 * bands)398 int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands)
399 {
400 	if (bands == NULL) {
401 		wpa_printf(MSG_DEBUG,  "WPS: No RF Bands received");
402 		return -1;
403 	}
404 
405 	dev->rf_bands = *bands;
406 	wpa_printf(MSG_DEBUG,  "WPS: Enrollee RF Bands 0x%x", dev->rf_bands);
407 
408 	return 0;
409 }
410 
411 
wps_device_data_dup(struct wps_device_data * dst,const struct wps_device_data * src)412 void wps_device_data_dup(struct wps_device_data *dst,
413 			 const struct wps_device_data *src)
414 {
415 	if (src->device_name)
416 		dst->device_name = os_strdup(src->device_name);
417 	if (src->manufacturer)
418 		dst->manufacturer = os_strdup(src->manufacturer);
419 	if (src->model_name)
420 		dst->model_name = os_strdup(src->model_name);
421 	if (src->model_number)
422 		dst->model_number = os_strdup(src->model_number);
423 	if (src->serial_number)
424 		dst->serial_number = os_strdup(src->serial_number);
425 	os_memcpy(dst->pri_dev_type, src->pri_dev_type, WPS_DEV_TYPE_LEN);
426 	dst->os_version = src->os_version;
427 	dst->rf_bands = src->rf_bands;
428 }
429 
430 
wps_device_data_free(struct wps_device_data * dev)431 void wps_device_data_free(struct wps_device_data *dev)
432 {
433 	os_free(dev->device_name);
434 	dev->device_name = NULL;
435 	os_free(dev->manufacturer);
436 	dev->manufacturer = NULL;
437 	os_free(dev->model_name);
438 	dev->model_name = NULL;
439 	os_free(dev->model_number);
440 	dev->model_number = NULL;
441 	os_free(dev->serial_number);
442 	dev->serial_number = NULL;
443 }
444