• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Wi-Fi Protected Setup - common functionality
3  * Copyright (c) 2008-2009, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14 
15 #include "includes.h"
16 
17 #include "common.h"
18 #include "crypto/aes_wrap.h"
19 #include "crypto/crypto.h"
20 #include "crypto/dh_group5.h"
21 #include "crypto/sha1.h"
22 #include "crypto/sha256.h"
23 #include "crypto/random.h"
24 #include "wps_i.h"
25 #include "wps_dev_attr.h"
26 
27 
wps_kdf(const u8 * key,const u8 * label_prefix,size_t label_prefix_len,const char * label,u8 * res,size_t res_len)28 void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len,
29 	     const char *label, u8 *res, size_t res_len)
30 {
31 	u8 i_buf[4], key_bits[4];
32 	const u8 *addr[4];
33 	size_t len[4];
34 	int i, iter;
35 	u8 hash[SHA256_MAC_LEN], *opos;
36 	size_t left;
37 
38 	WPA_PUT_BE32(key_bits, res_len * 8);
39 
40 	addr[0] = i_buf;
41 	len[0] = sizeof(i_buf);
42 	addr[1] = label_prefix;
43 	len[1] = label_prefix_len;
44 	addr[2] = (const u8 *) label;
45 	len[2] = os_strlen(label);
46 	addr[3] = key_bits;
47 	len[3] = sizeof(key_bits);
48 
49 	iter = (res_len + SHA256_MAC_LEN - 1) / SHA256_MAC_LEN;
50 	opos = res;
51 	left = res_len;
52 
53 	for (i = 1; i <= iter; i++) {
54 		WPA_PUT_BE32(i_buf, i);
55 		hmac_sha256_vector(key, SHA256_MAC_LEN, 4, addr, len, hash);
56 		if (i < iter) {
57 			os_memcpy(opos, hash, SHA256_MAC_LEN);
58 			opos += SHA256_MAC_LEN;
59 			left -= SHA256_MAC_LEN;
60 		} else
61 			os_memcpy(opos, hash, left);
62 	}
63 }
64 
65 
wps_derive_keys(struct wps_data * wps)66 int wps_derive_keys(struct wps_data *wps)
67 {
68 	struct wpabuf *pubkey, *dh_shared;
69 	u8 dhkey[SHA256_MAC_LEN], kdk[SHA256_MAC_LEN];
70 	const u8 *addr[3];
71 	size_t len[3];
72 	u8 keys[WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN + WPS_EMSK_LEN];
73 
74 	if (wps->dh_privkey == NULL) {
75 		wpa_printf(MSG_DEBUG, "WPS: Own DH private key not available");
76 		return -1;
77 	}
78 
79 	pubkey = wps->registrar ? wps->dh_pubkey_e : wps->dh_pubkey_r;
80 	if (pubkey == NULL) {
81 		wpa_printf(MSG_DEBUG, "WPS: Peer DH public key not available");
82 		return -1;
83 	}
84 
85 	wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH Private Key", wps->dh_privkey);
86 	wpa_hexdump_buf(MSG_DEBUG, "WPS: DH peer Public Key", pubkey);
87 	dh_shared = dh5_derive_shared(wps->dh_ctx, pubkey, wps->dh_privkey);
88 	dh5_free(wps->dh_ctx);
89 	wps->dh_ctx = NULL;
90 	dh_shared = wpabuf_zeropad(dh_shared, 192);
91 	if (dh_shared == NULL) {
92 		wpa_printf(MSG_DEBUG, "WPS: Failed to derive DH shared key");
93 		return -1;
94 	}
95 
96 	/* Own DH private key is not needed anymore */
97 	wpabuf_free(wps->dh_privkey);
98 	wps->dh_privkey = NULL;
99 
100 	wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH shared key", dh_shared);
101 
102 	/* DHKey = SHA-256(g^AB mod p) */
103 	addr[0] = wpabuf_head(dh_shared);
104 	len[0] = wpabuf_len(dh_shared);
105 	sha256_vector(1, addr, len, dhkey);
106 	wpa_hexdump_key(MSG_DEBUG, "WPS: DHKey", dhkey, sizeof(dhkey));
107 	wpabuf_free(dh_shared);
108 
109 	/* KDK = HMAC-SHA-256_DHKey(N1 || EnrolleeMAC || N2) */
110 	addr[0] = wps->nonce_e;
111 	len[0] = WPS_NONCE_LEN;
112 	addr[1] = wps->mac_addr_e;
113 	len[1] = ETH_ALEN;
114 	addr[2] = wps->nonce_r;
115 	len[2] = WPS_NONCE_LEN;
116 	hmac_sha256_vector(dhkey, sizeof(dhkey), 3, addr, len, kdk);
117 	wpa_hexdump_key(MSG_DEBUG, "WPS: KDK", kdk, sizeof(kdk));
118 
119 	wps_kdf(kdk, NULL, 0, "Wi-Fi Easy and Secure Key Derivation",
120 		keys, sizeof(keys));
121 	os_memcpy(wps->authkey, keys, WPS_AUTHKEY_LEN);
122 	os_memcpy(wps->keywrapkey, keys + WPS_AUTHKEY_LEN, WPS_KEYWRAPKEY_LEN);
123 	os_memcpy(wps->emsk, keys + WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN,
124 		  WPS_EMSK_LEN);
125 
126 	wpa_hexdump_key(MSG_DEBUG, "WPS: AuthKey",
127 			wps->authkey, WPS_AUTHKEY_LEN);
128 	wpa_hexdump_key(MSG_DEBUG, "WPS: KeyWrapKey",
129 			wps->keywrapkey, WPS_KEYWRAPKEY_LEN);
130 	wpa_hexdump_key(MSG_DEBUG, "WPS: EMSK", wps->emsk, WPS_EMSK_LEN);
131 
132 	return 0;
133 }
134 
135 
wps_derive_psk(struct wps_data * wps,const u8 * dev_passwd,size_t dev_passwd_len)136 void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd,
137 		    size_t dev_passwd_len)
138 {
139 	u8 hash[SHA256_MAC_LEN];
140 
141 	hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd,
142 		    (dev_passwd_len + 1) / 2, hash);
143 	os_memcpy(wps->psk1, hash, WPS_PSK_LEN);
144 	hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN,
145 		    dev_passwd + (dev_passwd_len + 1) / 2,
146 		    dev_passwd_len / 2, hash);
147 	os_memcpy(wps->psk2, hash, WPS_PSK_LEN);
148 
149 	wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Device Password",
150 			      dev_passwd, dev_passwd_len);
151 	wpa_hexdump_key(MSG_DEBUG, "WPS: PSK1", wps->psk1, WPS_PSK_LEN);
152 	wpa_hexdump_key(MSG_DEBUG, "WPS: PSK2", wps->psk2, WPS_PSK_LEN);
153 }
154 
155 
wps_decrypt_encr_settings(struct wps_data * wps,const u8 * encr,size_t encr_len)156 struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr,
157 					  size_t encr_len)
158 {
159 	struct wpabuf *decrypted;
160 	const size_t block_size = 16;
161 	size_t i;
162 	u8 pad;
163 	const u8 *pos;
164 
165 	/* AES-128-CBC */
166 	if (encr == NULL || encr_len < 2 * block_size || encr_len % block_size)
167 	{
168 		wpa_printf(MSG_DEBUG, "WPS: No Encrypted Settings received");
169 		return NULL;
170 	}
171 
172 	decrypted = wpabuf_alloc(encr_len - block_size);
173 	if (decrypted == NULL)
174 		return NULL;
175 
176 	wpa_hexdump(MSG_MSGDUMP, "WPS: Encrypted Settings", encr, encr_len);
177 	wpabuf_put_data(decrypted, encr + block_size, encr_len - block_size);
178 	if (aes_128_cbc_decrypt(wps->keywrapkey, encr, wpabuf_mhead(decrypted),
179 				wpabuf_len(decrypted))) {
180 		wpabuf_free(decrypted);
181 		return NULL;
182 	}
183 
184 	wpa_hexdump_buf_key(MSG_MSGDUMP, "WPS: Decrypted Encrypted Settings",
185 			    decrypted);
186 
187 	pos = wpabuf_head_u8(decrypted) + wpabuf_len(decrypted) - 1;
188 	pad = *pos;
189 	if (pad > wpabuf_len(decrypted)) {
190 		wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad value");
191 		wpabuf_free(decrypted);
192 		return NULL;
193 	}
194 	for (i = 0; i < pad; i++) {
195 		if (*pos-- != pad) {
196 			wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad "
197 				   "string");
198 			wpabuf_free(decrypted);
199 			return NULL;
200 		}
201 	}
202 	decrypted->used -= pad;
203 
204 	return decrypted;
205 }
206 
207 
208 /**
209  * wps_pin_checksum - Compute PIN checksum
210  * @pin: Seven digit PIN (i.e., eight digit PIN without the checksum digit)
211  * Returns: Checksum digit
212  */
wps_pin_checksum(unsigned int pin)213 unsigned int wps_pin_checksum(unsigned int pin)
214 {
215 	unsigned int accum = 0;
216 	while (pin) {
217 		accum += 3 * (pin % 10);
218 		pin /= 10;
219 		accum += pin % 10;
220 		pin /= 10;
221 	}
222 
223 	return (10 - accum % 10) % 10;
224 }
225 
226 
227 /**
228  * wps_pin_valid - Check whether a PIN has a valid checksum
229  * @pin: Eight digit PIN (i.e., including the checksum digit)
230  * Returns: 1 if checksum digit is valid, or 0 if not
231  */
wps_pin_valid(unsigned int pin)232 unsigned int wps_pin_valid(unsigned int pin)
233 {
234 	return wps_pin_checksum(pin / 10) == (pin % 10);
235 }
236 
237 
238 /**
239  * wps_generate_pin - Generate a random PIN
240  * Returns: Eight digit PIN (i.e., including the checksum digit)
241  */
wps_generate_pin(void)242 unsigned int wps_generate_pin(void)
243 {
244 	unsigned int val;
245 
246 	/* Generate seven random digits for the PIN */
247 	if (random_get_bytes((unsigned char *) &val, sizeof(val)) < 0) {
248 		struct os_time now;
249 		os_get_time(&now);
250 		val = os_random() ^ now.sec ^ now.usec;
251 	}
252 	val %= 10000000;
253 
254 	/* Append checksum digit */
255 	return val * 10 + wps_pin_checksum(val);
256 }
257 
258 
wps_fail_event(struct wps_context * wps,enum wps_msg_type msg,u16 config_error,u16 error_indication)259 void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg,
260 		    u16 config_error, u16 error_indication)
261 {
262 	union wps_event_data data;
263 
264 	if (wps->event_cb == NULL)
265 		return;
266 
267 	os_memset(&data, 0, sizeof(data));
268 	data.fail.msg = msg;
269 	data.fail.config_error = config_error;
270 	data.fail.error_indication = error_indication;
271 	wps->event_cb(wps->cb_ctx, WPS_EV_FAIL, &data);
272 }
273 
274 
wps_success_event(struct wps_context * wps)275 void wps_success_event(struct wps_context *wps)
276 {
277 	if (wps->event_cb == NULL)
278 		return;
279 
280 	wps->event_cb(wps->cb_ctx, WPS_EV_SUCCESS, NULL);
281 }
282 
283 
wps_pwd_auth_fail_event(struct wps_context * wps,int enrollee,int part)284 void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part)
285 {
286 	union wps_event_data data;
287 
288 	if (wps->event_cb == NULL)
289 		return;
290 
291 	os_memset(&data, 0, sizeof(data));
292 	data.pwd_auth_fail.enrollee = enrollee;
293 	data.pwd_auth_fail.part = part;
294 	wps->event_cb(wps->cb_ctx, WPS_EV_PWD_AUTH_FAIL, &data);
295 }
296 
297 
wps_pbc_overlap_event(struct wps_context * wps)298 void wps_pbc_overlap_event(struct wps_context *wps)
299 {
300 	if (wps->event_cb == NULL)
301 		return;
302 
303 	wps->event_cb(wps->cb_ctx, WPS_EV_PBC_OVERLAP, NULL);
304 }
305 
306 
wps_pbc_timeout_event(struct wps_context * wps)307 void wps_pbc_timeout_event(struct wps_context *wps)
308 {
309 	if (wps->event_cb == NULL)
310 		return;
311 
312 	wps->event_cb(wps->cb_ctx, WPS_EV_PBC_TIMEOUT, NULL);
313 }
314 
315 
316 #ifdef CONFIG_WPS_OOB
317 
wps_get_oob_cred(struct wps_context * wps)318 static struct wpabuf * wps_get_oob_cred(struct wps_context *wps)
319 {
320 	struct wps_data data;
321 	struct wpabuf *plain;
322 
323 	plain = wpabuf_alloc(500);
324 	if (plain == NULL) {
325 		wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
326 			   "credential");
327 		return NULL;
328 	}
329 
330 	os_memset(&data, 0, sizeof(data));
331 	data.wps = wps;
332 	data.auth_type = wps->auth_types;
333 	data.encr_type = wps->encr_types;
334 	if (wps_build_version(plain) ||
335 	    wps_build_cred(&data, plain) ||
336 	    wps_build_wfa_ext(plain, 0, NULL, 0)) {
337 		wpabuf_free(plain);
338 		return NULL;
339 	}
340 
341 	return plain;
342 }
343 
344 
wps_get_oob_dev_pwd(struct wps_context * wps)345 static struct wpabuf * wps_get_oob_dev_pwd(struct wps_context *wps)
346 {
347 	struct wpabuf *data;
348 
349 	data = wpabuf_alloc(9 + WPS_OOB_DEVICE_PASSWORD_ATTR_LEN);
350 	if (data == NULL) {
351 		wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
352 			   "device password attribute");
353 		return NULL;
354 	}
355 
356 	wpabuf_free(wps->oob_conf.dev_password);
357 	wps->oob_conf.dev_password =
358 		wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1);
359 	if (wps->oob_conf.dev_password == NULL) {
360 		wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
361 			   "device password");
362 		wpabuf_free(data);
363 		return NULL;
364 	}
365 
366 	if (wps_build_version(data) ||
367 	    wps_build_oob_dev_password(data, wps) ||
368 	    wps_build_wfa_ext(data, 0, NULL, 0)) {
369 		wpa_printf(MSG_ERROR, "WPS: Build OOB device password "
370 			   "attribute error");
371 		wpabuf_free(data);
372 		return NULL;
373 	}
374 
375 	return data;
376 }
377 
378 
wps_parse_oob_dev_pwd(struct wps_context * wps,struct wpabuf * data)379 static int wps_parse_oob_dev_pwd(struct wps_context *wps,
380 				 struct wpabuf *data)
381 {
382 	struct oob_conf_data *oob_conf = &wps->oob_conf;
383 	struct wps_parse_attr attr;
384 	const u8 *pos;
385 
386 	if (wps_parse_msg(data, &attr) < 0 ||
387 	    attr.oob_dev_password == NULL) {
388 		wpa_printf(MSG_ERROR, "WPS: OOB device password not found");
389 		return -1;
390 	}
391 
392 	pos = attr.oob_dev_password;
393 
394 	oob_conf->pubkey_hash =
395 		wpabuf_alloc_copy(pos, WPS_OOB_PUBKEY_HASH_LEN);
396 	if (oob_conf->pubkey_hash == NULL) {
397 		wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
398 			   "public key hash");
399 		return -1;
400 	}
401 	pos += WPS_OOB_PUBKEY_HASH_LEN;
402 
403 	wps->oob_dev_pw_id = WPA_GET_BE16(pos);
404 	pos += sizeof(wps->oob_dev_pw_id);
405 
406 	oob_conf->dev_password =
407 		wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1);
408 	if (oob_conf->dev_password == NULL) {
409 		wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
410 			   "device password");
411 		return -1;
412 	}
413 	wpa_snprintf_hex_uppercase(wpabuf_put(oob_conf->dev_password,
414 				   wpabuf_size(oob_conf->dev_password)),
415 				   wpabuf_size(oob_conf->dev_password), pos,
416 				   WPS_OOB_DEVICE_PASSWORD_LEN);
417 
418 	return 0;
419 }
420 
421 
wps_parse_oob_cred(struct wps_context * wps,struct wpabuf * data)422 static int wps_parse_oob_cred(struct wps_context *wps, struct wpabuf *data)
423 {
424 	struct wpabuf msg;
425 	struct wps_parse_attr attr;
426 	size_t i;
427 
428 	if (wps_parse_msg(data, &attr) < 0 || attr.num_cred <= 0) {
429 		wpa_printf(MSG_ERROR, "WPS: OOB credential not found");
430 		return -1;
431 	}
432 
433 	for (i = 0; i < attr.num_cred; i++) {
434 		struct wps_credential local_cred;
435 		struct wps_parse_attr cattr;
436 
437 		os_memset(&local_cred, 0, sizeof(local_cred));
438 		wpabuf_set(&msg, attr.cred[i], attr.cred_len[i]);
439 		if (wps_parse_msg(&msg, &cattr) < 0 ||
440 		    wps_process_cred(&cattr, &local_cred)) {
441 			wpa_printf(MSG_ERROR, "WPS: Failed to parse OOB "
442 				   "credential");
443 			return -1;
444 		}
445 		wps->cred_cb(wps->cb_ctx, &local_cred);
446 	}
447 
448 	return 0;
449 }
450 
451 
wps_process_oob(struct wps_context * wps,struct oob_device_data * oob_dev,int registrar)452 int wps_process_oob(struct wps_context *wps, struct oob_device_data *oob_dev,
453 		    int registrar)
454 {
455 	struct wpabuf *data;
456 	int ret, write_f, oob_method = wps->oob_conf.oob_method;
457 	void *oob_priv;
458 
459 	write_f = oob_method == OOB_METHOD_DEV_PWD_E ? !registrar : registrar;
460 
461 	oob_priv = oob_dev->init_func(wps, oob_dev, registrar);
462 	if (oob_priv == NULL) {
463 		wpa_printf(MSG_ERROR, "WPS: Failed to initialize OOB device");
464 		return -1;
465 	}
466 
467 	if (write_f) {
468 		if (oob_method == OOB_METHOD_CRED)
469 			data = wps_get_oob_cred(wps);
470 		else
471 			data = wps_get_oob_dev_pwd(wps);
472 
473 		ret = 0;
474 		if (data == NULL || oob_dev->write_func(oob_priv, data) < 0)
475 			ret = -1;
476 	} else {
477 		data = oob_dev->read_func(oob_priv);
478 		if (data == NULL)
479 			ret = -1;
480 		else {
481 			if (oob_method == OOB_METHOD_CRED)
482 				ret = wps_parse_oob_cred(wps, data);
483 			else
484 				ret = wps_parse_oob_dev_pwd(wps, data);
485 		}
486 	}
487 	wpabuf_free(data);
488 	oob_dev->deinit_func(oob_priv);
489 
490 	if (ret < 0) {
491 		wpa_printf(MSG_ERROR, "WPS: Failed to process OOB data");
492 		return -1;
493 	}
494 
495 	return 0;
496 }
497 
498 
wps_get_oob_device(char * device_type)499 struct oob_device_data * wps_get_oob_device(char *device_type)
500 {
501 #ifdef CONFIG_WPS_UFD
502 	if (os_strstr(device_type, "ufd") != NULL)
503 		return &oob_ufd_device_data;
504 #endif /* CONFIG_WPS_UFD */
505 #ifdef CONFIG_WPS_NFC
506 	if (os_strstr(device_type, "nfc") != NULL)
507 		return &oob_nfc_device_data;
508 #endif /* CONFIG_WPS_NFC */
509 
510 	return NULL;
511 }
512 
513 
514 #ifdef CONFIG_WPS_NFC
wps_get_oob_nfc_device(char * device_name)515 struct oob_nfc_device_data * wps_get_oob_nfc_device(char *device_name)
516 {
517 	if (device_name == NULL)
518 		return NULL;
519 #ifdef CONFIG_WPS_NFC_PN531
520 	if (os_strstr(device_name, "pn531") != NULL)
521 		return &oob_nfc_pn531_device_data;
522 #endif /* CONFIG_WPS_NFC_PN531 */
523 
524 	return NULL;
525 }
526 #endif /* CONFIG_WPS_NFC */
527 
528 
wps_get_oob_method(char * method)529 int wps_get_oob_method(char *method)
530 {
531 	if (os_strstr(method, "pin-e") != NULL)
532 		return OOB_METHOD_DEV_PWD_E;
533 	if (os_strstr(method, "pin-r") != NULL)
534 		return OOB_METHOD_DEV_PWD_R;
535 	if (os_strstr(method, "cred") != NULL)
536 		return OOB_METHOD_CRED;
537 	return OOB_METHOD_UNKNOWN;
538 }
539 
540 #endif /* CONFIG_WPS_OOB */
541 
542 
wps_dev_type_str2bin(const char * str,u8 dev_type[WPS_DEV_TYPE_LEN])543 int wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN])
544 {
545 	const char *pos;
546 
547 	/* <categ>-<OUI>-<subcateg> */
548 	WPA_PUT_BE16(dev_type, atoi(str));
549 	pos = os_strchr(str, '-');
550 	if (pos == NULL)
551 		return -1;
552 	pos++;
553 	if (hexstr2bin(pos, &dev_type[2], 4))
554 		return -1;
555 	pos = os_strchr(pos, '-');
556 	if (pos == NULL)
557 		return -1;
558 	pos++;
559 	WPA_PUT_BE16(&dev_type[6], atoi(pos));
560 
561 
562 	return 0;
563 }
564 
565 
wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN],char * buf,size_t buf_len)566 char * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf,
567 			    size_t buf_len)
568 {
569 	int ret;
570 
571 	ret = os_snprintf(buf, buf_len, "%u-%08X-%u",
572 			  WPA_GET_BE16(dev_type), WPA_GET_BE32(&dev_type[2]),
573 			  WPA_GET_BE16(&dev_type[6]));
574 	if (ret < 0 || (unsigned int) ret >= buf_len)
575 		return NULL;
576 
577 	return buf;
578 }
579 
580 
uuid_gen_mac_addr(const u8 * mac_addr,u8 * uuid)581 void uuid_gen_mac_addr(const u8 *mac_addr, u8 *uuid)
582 {
583 	const u8 *addr[2];
584 	size_t len[2];
585 	u8 hash[SHA1_MAC_LEN];
586 	u8 nsid[16] = {
587 		0x52, 0x64, 0x80, 0xf8,
588 		0xc9, 0x9b,
589 		0x4b, 0xe5,
590 		0xa6, 0x55,
591 		0x58, 0xed, 0x5f, 0x5d, 0x60, 0x84
592 	};
593 
594 	addr[0] = nsid;
595 	len[0] = sizeof(nsid);
596 	addr[1] = mac_addr;
597 	len[1] = 6;
598 	sha1_vector(2, addr, len, hash);
599 	os_memcpy(uuid, hash, 16);
600 
601 	/* Version: 5 = named-based version using SHA-1 */
602 	uuid[6] = (5 << 4) | (uuid[6] & 0x0f);
603 
604 	/* Variant specified in RFC 4122 */
605 	uuid[8] = 0x80 | (uuid[8] & 0x3f);
606 }
607 
608 
wps_config_methods_str2bin(const char * str)609 u16 wps_config_methods_str2bin(const char *str)
610 {
611 	u16 methods = 0;
612 
613 	if (str == NULL) {
614 		/* Default to enabling methods based on build configuration */
615 		methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD;
616 #ifdef CONFIG_WPS2
617 		methods |= WPS_CONFIG_VIRT_DISPLAY;
618 #endif /* CONFIG_WPS2 */
619 #ifdef CONFIG_WPS_UFD
620 		methods |= WPS_CONFIG_USBA;
621 #endif /* CONFIG_WPS_UFD */
622 #ifdef CONFIG_WPS_NFC
623 		methods |= WPS_CONFIG_NFC_INTERFACE;
624 #endif /* CONFIG_WPS_NFC */
625 	} else {
626 		if (os_strstr(str, "usba"))
627 			methods |= WPS_CONFIG_USBA;
628 		if (os_strstr(str, "ethernet"))
629 			methods |= WPS_CONFIG_ETHERNET;
630 		if (os_strstr(str, "label"))
631 			methods |= WPS_CONFIG_LABEL;
632 		if (os_strstr(str, "display"))
633 			methods |= WPS_CONFIG_DISPLAY;
634 		if (os_strstr(str, "ext_nfc_token"))
635 			methods |= WPS_CONFIG_EXT_NFC_TOKEN;
636 		if (os_strstr(str, "int_nfc_token"))
637 			methods |= WPS_CONFIG_INT_NFC_TOKEN;
638 		if (os_strstr(str, "nfc_interface"))
639 			methods |= WPS_CONFIG_NFC_INTERFACE;
640 		if (os_strstr(str, "push_button"))
641 			methods |= WPS_CONFIG_PUSHBUTTON;
642 		if (os_strstr(str, "keypad"))
643 			methods |= WPS_CONFIG_KEYPAD;
644 #ifdef CONFIG_WPS2
645 		if (os_strstr(str, "virtual_display"))
646 			methods |= WPS_CONFIG_VIRT_DISPLAY;
647 		if (os_strstr(str, "physical_display"))
648 			methods |= WPS_CONFIG_PHY_DISPLAY;
649 		if (os_strstr(str, "virtual_push_button"))
650 			methods |= WPS_CONFIG_VIRT_PUSHBUTTON;
651 		if (os_strstr(str, "physical_push_button"))
652 			methods |= WPS_CONFIG_PHY_PUSHBUTTON;
653 #endif /* CONFIG_WPS2 */
654 	}
655 
656 	return methods;
657 }
658 
659 
wps_build_wsc_ack(struct wps_data * wps)660 struct wpabuf * wps_build_wsc_ack(struct wps_data *wps)
661 {
662 	struct wpabuf *msg;
663 
664 	wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_ACK");
665 
666 	msg = wpabuf_alloc(1000);
667 	if (msg == NULL)
668 		return NULL;
669 
670 	if (wps_build_version(msg) ||
671 	    wps_build_msg_type(msg, WPS_WSC_ACK) ||
672 	    wps_build_enrollee_nonce(wps, msg) ||
673 	    wps_build_registrar_nonce(wps, msg) ||
674 	    wps_build_wfa_ext(msg, 0, NULL, 0)) {
675 		wpabuf_free(msg);
676 		return NULL;
677 	}
678 
679 	return msg;
680 }
681 
682 
wps_build_wsc_nack(struct wps_data * wps)683 struct wpabuf * wps_build_wsc_nack(struct wps_data *wps)
684 {
685 	struct wpabuf *msg;
686 
687 	wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_NACK");
688 
689 	msg = wpabuf_alloc(1000);
690 	if (msg == NULL)
691 		return NULL;
692 
693 	if (wps_build_version(msg) ||
694 	    wps_build_msg_type(msg, WPS_WSC_NACK) ||
695 	    wps_build_enrollee_nonce(wps, msg) ||
696 	    wps_build_registrar_nonce(wps, msg) ||
697 	    wps_build_config_error(msg, wps->config_error) ||
698 	    wps_build_wfa_ext(msg, 0, NULL, 0)) {
699 		wpabuf_free(msg);
700 		return NULL;
701 	}
702 
703 	return msg;
704 }
705