1 /*
2  * Wi-Fi Protected Setup - common functionality
3  * Copyright (c) 2008-2012, 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 
9 #include "includes.h"
10 
11 #include "common.h"
12 #include "common/defs.h"
13 #include "common/ieee802_11_common.h"
14 #include "crypto/aes_wrap.h"
15 #include "crypto/crypto.h"
16 #include "crypto/dh_group5.h"
17 #include "crypto/sha1.h"
18 #include "crypto/sha256.h"
19 #include "crypto/random.h"
20 #include "wps_i.h"
21 #include "wps_dev_attr.h"
22 
23 
wps_kdf(const u8 * key,const u8 * label_prefix,size_t label_prefix_len,const char * label,u8 * res,size_t res_len)24 void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len,
25 	     const char *label, u8 *res, size_t res_len)
26 {
27 	u8 i_buf[4], key_bits[4];
28 	const u8 *addr[4];
29 	size_t len[4];
30 	int i, iter;
31 	u8 hash[SHA256_MAC_LEN], *opos;
32 	size_t left;
33 
34 	WPA_PUT_BE32(key_bits, res_len * 8);
35 
36 	addr[0] = i_buf;
37 	len[0] = sizeof(i_buf);
38 	addr[1] = label_prefix;
39 	len[1] = label_prefix_len;
40 	addr[2] = (const u8 *) label;
41 	len[2] = os_strlen(label);
42 	addr[3] = key_bits;
43 	len[3] = sizeof(key_bits);
44 
45 	iter = (res_len + SHA256_MAC_LEN - 1) / SHA256_MAC_LEN;
46 	opos = res;
47 	left = res_len;
48 
49 	for (i = 1; i <= iter; i++) {
50 		WPA_PUT_BE32(i_buf, i);
51 		hmac_sha256_vector(key, SHA256_MAC_LEN, 4, addr, len, hash);
52 		if (i < iter) {
53 			os_memcpy(opos, hash, SHA256_MAC_LEN);
54 			opos += SHA256_MAC_LEN;
55 			left -= SHA256_MAC_LEN;
56 		} else
57 			os_memcpy(opos, hash, left);
58 	}
59 }
60 
61 
wps_derive_keys(struct wps_data * wps)62 int wps_derive_keys(struct wps_data *wps)
63 {
64 	struct wpabuf *pubkey, *dh_shared;
65 	u8 dhkey[SHA256_MAC_LEN], kdk[SHA256_MAC_LEN];
66 	const u8 *addr[3];
67 	size_t len[3];
68 	u8 keys[WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN + WPS_EMSK_LEN];
69 
70 	if (wps->dh_privkey == NULL) {
71 		wpa_printf(MSG_DEBUG, "WPS: Own DH private key not available");
72 		return -1;
73 	}
74 
75 	pubkey = wps->registrar ? wps->dh_pubkey_e : wps->dh_pubkey_r;
76 	if (pubkey == NULL) {
77 		wpa_printf(MSG_DEBUG, "WPS: Peer DH public key not available");
78 		return -1;
79 	}
80 
81 	wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH Private Key", wps->dh_privkey);
82 	wpa_hexdump_buf(MSG_DEBUG, "WPS: DH peer Public Key", pubkey);
83 	dh_shared = dh5_derive_shared(wps->dh_ctx, pubkey, wps->dh_privkey);
84 	dh5_free(wps->dh_ctx);
85 	wps->dh_ctx = NULL;
86 	dh_shared = wpabuf_zeropad(dh_shared, 192);
87 	if (dh_shared == NULL) {
88 		wpa_printf(MSG_DEBUG, "WPS: Failed to derive DH shared key");
89 		return -1;
90 	}
91 
92 	/* Own DH private key is not needed anymore */
93 	/*
94 	 * due to the public key calculated when wps start, it will not calculate anymore even when we build M1 message, also calculate the key need take a long time
95 	 * which would cause WPS fail, so we clean the key after WPS finished .
96 	 */
97 #ifndef ESP_SUPPLICANT
98 	wpabuf_clear_free(wps->dh_privkey);
99 	wps->dh_privkey = NULL;
100 #endif /* ESP_SUPPLICANT */
101 
102 	wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH shared key", dh_shared);
103 
104 	/* DHKey = SHA-256(g^AB mod p) */
105 	addr[0] = wpabuf_head(dh_shared);
106 	len[0] = wpabuf_len(dh_shared);
107 	sha256_vector(1, addr, len, dhkey);
108 	wpa_hexdump_key(MSG_DEBUG, "WPS: DHKey", dhkey, sizeof(dhkey));
109 	wpabuf_clear_free(dh_shared);
110 
111 	/* KDK = HMAC-SHA-256_DHKey(N1 || EnrolleeMAC || N2) */
112 	addr[0] = wps->nonce_e;
113 	len[0] = WPS_NONCE_LEN;
114 	addr[1] = wps->mac_addr_e;
115 	len[1] = ETH_ALEN;
116 	addr[2] = wps->nonce_r;
117 	len[2] = WPS_NONCE_LEN;
118 	hmac_sha256_vector(dhkey, sizeof(dhkey), 3, addr, len, kdk);
119 	wpa_hexdump_key(MSG_DEBUG, "WPS: KDK", kdk, sizeof(kdk));
120 
121 	wps_kdf(kdk, NULL, 0, "Wi-Fi Easy and Secure Key Derivation",
122 		keys, sizeof(keys));
123 	os_memcpy(wps->authkey, keys, WPS_AUTHKEY_LEN);
124 	os_memcpy(wps->keywrapkey, keys + WPS_AUTHKEY_LEN, WPS_KEYWRAPKEY_LEN);
125 	os_memcpy(wps->emsk, keys + WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN,
126 		  WPS_EMSK_LEN);
127 
128 	wpa_hexdump_key(MSG_DEBUG, "WPS: AuthKey",
129 			wps->authkey, WPS_AUTHKEY_LEN);
130 	wpa_hexdump_key(MSG_DEBUG, "WPS: KeyWrapKey",
131 			wps->keywrapkey, WPS_KEYWRAPKEY_LEN);
132 	wpa_hexdump_key(MSG_DEBUG, "WPS: EMSK", wps->emsk, WPS_EMSK_LEN);
133 
134 	return 0;
135 }
136 
137 
wps_derive_psk(struct wps_data * wps,const u8 * dev_passwd,size_t dev_passwd_len)138 int wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd,
139 		   size_t dev_passwd_len)
140 {
141 	u8 hash[SHA256_MAC_LEN];
142 
143 	if (hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd,
144 			(dev_passwd_len + 1) / 2, hash) < 0)
145 		return -1;
146 	os_memcpy(wps->psk1, hash, WPS_PSK_LEN);
147 	if (hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN,
148 			dev_passwd + (dev_passwd_len + 1) / 2,
149 			dev_passwd_len / 2, hash) < 0)
150 		return -1;
151 	os_memcpy(wps->psk2, hash, WPS_PSK_LEN);
152 
153 	wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Device Password",
154 			      dev_passwd, dev_passwd_len);
155 	wpa_hexdump_key(MSG_DEBUG, "WPS: PSK1", wps->psk1, WPS_PSK_LEN);
156 	wpa_hexdump_key(MSG_DEBUG, "WPS: PSK2", wps->psk2, WPS_PSK_LEN);
157 	return 0;
158 }
159 
160 
wps_decrypt_encr_settings(struct wps_data * wps,const u8 * encr,size_t encr_len)161 struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr,
162 					  size_t encr_len)
163 {
164 	struct wpabuf *decrypted;
165 	const size_t block_size = 16;
166 	size_t i;
167 	u8 pad;
168 	const u8 *pos;
169 
170 	/* AES-128-CBC */
171 	if (encr == NULL || encr_len < 2 * block_size || encr_len % block_size)
172 	{
173 		wpa_printf(MSG_DEBUG, "WPS: No Encrypted Settings received");
174 		return NULL;
175 	}
176 
177 	decrypted = wpabuf_alloc(encr_len - block_size);
178 	if (decrypted == NULL)
179 		return NULL;
180 
181 	wpa_hexdump(MSG_MSGDUMP, "WPS: Encrypted Settings", encr, encr_len);
182 	wpabuf_put_data(decrypted, encr + block_size, encr_len - block_size);
183 	if (aes_128_cbc_decrypt(wps->keywrapkey, encr, wpabuf_mhead(decrypted),
184 				wpabuf_len(decrypted))) {
185 		wpabuf_clear_free(decrypted);
186 		return NULL;
187 	}
188 
189 	wpa_hexdump_buf_key(MSG_MSGDUMP, "WPS: Decrypted Encrypted Settings",
190 			    decrypted);
191 
192 	pos = wpabuf_head_u8(decrypted) + wpabuf_len(decrypted) - 1;
193 	pad = *pos;
194 	if (pad > wpabuf_len(decrypted)) {
195 		wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad value");
196 		wpabuf_clear_free(decrypted);
197 		return NULL;
198 	}
199 	for (i = 0; i < pad; i++) {
200 		if (*pos-- != pad) {
201 			wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad "
202 				   "string");
203 			wpabuf_clear_free(decrypted);
204 			return NULL;
205 		}
206 	}
207 	decrypted->used -= pad;
208 
209 	return decrypted;
210 }
211 
212 
213 /**
214  * wps_pin_checksum - Compute PIN checksum
215  * @pin: Seven digit PIN (i.e., eight digit PIN without the checksum digit)
216  * Returns: Checksum digit
217  */
wps_pin_checksum(unsigned int pin)218 unsigned int wps_pin_checksum(unsigned int pin)
219 {
220 	unsigned int accum = 0;
221 	while (pin) {
222 		accum += 3 * (pin % 10);
223 		pin /= 10;
224 		accum += pin % 10;
225 		pin /= 10;
226 	}
227 
228 	return (10 - accum % 10) % 10;
229 }
230 
231 
232 /**
233  * wps_pin_valid - Check whether a PIN has a valid checksum
234  * @pin: Eight digit PIN (i.e., including the checksum digit)
235  * Returns: 1 if checksum digit is valid, or 0 if not
236  */
wps_pin_valid(unsigned int pin)237 unsigned int wps_pin_valid(unsigned int pin)
238 {
239 	return wps_pin_checksum(pin / 10) == (pin % 10);
240 }
241 
242 
243 /**
244  * wps_generate_pin - Generate a random PIN
245  * Returns: Eight digit PIN (i.e., including the checksum digit)
246  */
wps_generate_pin(unsigned int * pin)247 int wps_generate_pin(unsigned int *pin)
248 {
249 	unsigned int val;
250 
251 	/* Generate seven random digits for the PIN */
252 	if (random_get_bytes((unsigned char *) &val, sizeof(val)) < 0)
253 		return -1;
254 	val %= 10000000;
255 
256 	/* Append checksum digit */
257 	*pin = val * 10 + wps_pin_checksum(val);
258 	return 0;
259 }
260 
261 
wps_pin_str_valid(const char * pin)262 int wps_pin_str_valid(const char *pin)
263 {
264 	const char *p;
265 	size_t len;
266 
267 	p = pin;
268 	while (*p >= '0' && *p <= '9')
269 		p++;
270 	if (*p != '\0')
271 		return 0;
272 
273 	len = p - pin;
274 	return len == 4 || len == 8;
275 }
276 
277 
wps_fail_event(struct wps_context * wps,enum wps_msg_type msg,u16 config_error,u16 error_indication,const u8 * mac_addr)278 void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg,
279 		    u16 config_error, u16 error_indication, const u8 *mac_addr)
280 {
281 	union wps_event_data data;
282 
283 	if (wps->event_cb == NULL)
284 		return;
285 
286 	os_memset(&data, 0, sizeof(data));
287 	data.fail.msg = msg;
288 	data.fail.config_error = config_error;
289 	data.fail.error_indication = error_indication;
290 	os_memcpy(data.fail.peer_macaddr, mac_addr, ETH_ALEN);
291 	wps->event_cb(wps->cb_ctx, WPS_EV_FAIL, &data);
292 }
293 
294 
wps_success_event(struct wps_context * wps,const u8 * mac_addr)295 void wps_success_event(struct wps_context *wps, const u8 *mac_addr)
296 {
297 	union wps_event_data data;
298 
299 	if (wps->event_cb == NULL)
300 		return;
301 
302 	os_memset(&data, 0, sizeof(data));
303 	os_memcpy(data.success.peer_macaddr, mac_addr, ETH_ALEN);
304 	wps->event_cb(wps->cb_ctx, WPS_EV_SUCCESS, &data);
305 }
306 
307 
wps_pwd_auth_fail_event(struct wps_context * wps,int enrollee,int part,const u8 * mac_addr)308 void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part,
309 			     const u8 *mac_addr)
310 {
311 	union wps_event_data data;
312 
313 	if (wps->event_cb == NULL)
314 		return;
315 
316 	os_memset(&data, 0, sizeof(data));
317 	data.pwd_auth_fail.enrollee = enrollee;
318 	data.pwd_auth_fail.part = part;
319 	os_memcpy(data.pwd_auth_fail.peer_macaddr, mac_addr, ETH_ALEN);
320 	wps->event_cb(wps->cb_ctx, WPS_EV_PWD_AUTH_FAIL, &data);
321 }
322 
323 
wps_pbc_overlap_event(struct wps_context * wps)324 void wps_pbc_overlap_event(struct wps_context *wps)
325 {
326 	if (wps->event_cb == NULL)
327 		return;
328 
329 	wps->event_cb(wps->cb_ctx, WPS_EV_PBC_OVERLAP, NULL);
330 }
331 
332 
wps_selected_registrar_timeout_event(struct wps_context * wps)333 void wps_selected_registrar_timeout_event(struct wps_context *wps)
334 {
335 	if (wps->event_cb == NULL)
336 		return;
337 
338 	wps->event_cb(wps->cb_ctx, WPS_EV_SELECTED_REGISTRAR_TIMEOUT, NULL);
339 }
340 
wps_pbc_timeout_event(struct wps_context * wps)341 void wps_pbc_timeout_event(struct wps_context *wps)
342 {
343 	if (wps->event_cb == NULL)
344 		return;
345 
346 	wps->event_cb(wps->cb_ctx, WPS_EV_PBC_TIMEOUT, NULL);
347 }
348 
349 
wps_pbc_active_event(struct wps_context * wps)350 void wps_pbc_active_event(struct wps_context *wps)
351 {
352 	if (wps->event_cb == NULL)
353 		return;
354 
355 	wps->event_cb(wps->cb_ctx, WPS_EV_PBC_ACTIVE, NULL);
356 }
357 
358 
wps_pbc_disable_event(struct wps_context * wps)359 void wps_pbc_disable_event(struct wps_context *wps)
360 {
361 	if (wps->event_cb == NULL)
362 		return;
363 
364 	wps->event_cb(wps->cb_ctx, WPS_EV_PBC_DISABLE, NULL);
365 }
366 
367 
368 #ifdef CONFIG_WPS_OOB
369 
wps_get_oob_cred(struct wps_context * wps,int rf_band,int channel)370 struct wpabuf * wps_get_oob_cred(struct wps_context *wps, int rf_band,
371 				 int channel)
372 {
373 	struct wps_data data;
374 	struct wpabuf *plain;
375 
376 	plain = wpabuf_alloc(500);
377 	if (plain == NULL) {
378 		wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
379 			   "credential");
380 		return NULL;
381 	}
382 
383 	os_memset(&data, 0, sizeof(data));
384 	data.wps = wps;
385 	data.auth_type = wps->auth_types;
386 	data.encr_type = wps->encr_types;
387 	if (wps_build_cred(&data, plain) ||
388 	    (rf_band && wps_build_rf_bands_attr(plain, rf_band)) ||
389 	    (channel && wps_build_ap_channel(plain, channel)) ||
390 	    wps_build_mac_addr(plain, wps->dev.mac_addr) ||
391 	    wps_build_wfa_ext(plain, 0, NULL, 0, 0)) {
392 		os_free(data.new_psk);
393 		wpabuf_clear_free(plain);
394 		return NULL;
395 	}
396 
397 	if (wps->wps_state == WPS_STATE_NOT_CONFIGURED && data.new_psk &&
398 	    wps->ap) {
399 		struct wps_credential cred;
400 
401 		wpa_printf(MSG_DEBUG, "WPS: Moving to Configured state based "
402 			   "on credential token generation");
403 
404 		os_memset(&cred, 0, sizeof(cred));
405 		os_memcpy(cred.ssid, wps->ssid, wps->ssid_len);
406 		cred.ssid_len = wps->ssid_len;
407 		cred.auth_type = WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK;
408 		cred.encr_type = WPS_ENCR_TKIP | WPS_ENCR_AES;
409 		os_memcpy(cred.key, data.new_psk, data.new_psk_len);
410 		cred.key_len = data.new_psk_len;
411 
412 		wps->wps_state = WPS_STATE_CONFIGURED;
413 		wpa_hexdump_ascii_key(MSG_DEBUG,
414 				      "WPS: Generated random passphrase",
415 				      data.new_psk, data.new_psk_len);
416 		if (wps->cred_cb)
417 			wps->cred_cb(wps->cb_ctx, &cred);
418 	}
419 
420 	os_free(data.new_psk);
421 
422 	return plain;
423 }
424 
425 #ifdef CONFIG_WPS_NFC
426 
wps_build_nfc_pw_token(u16 dev_pw_id,const struct wpabuf * pubkey,const struct wpabuf * dev_pw)427 struct wpabuf * wps_build_nfc_pw_token(u16 dev_pw_id,
428 				       const struct wpabuf *pubkey,
429 				       const struct wpabuf *dev_pw)
430 {
431 	struct wpabuf *data;
432 
433 	data = wpabuf_alloc(200);
434 	if (data == NULL)
435 		return NULL;
436 
437 	if (wps_build_oob_dev_pw(data, dev_pw_id, pubkey,
438 				 wpabuf_head(dev_pw), wpabuf_len(dev_pw)) ||
439 	    wps_build_wfa_ext(data, 0, NULL, 0, 0)) {
440 		wpa_printf(MSG_ERROR, "WPS: Failed to build NFC password "
441 			   "token");
442 		wpabuf_clear_free(data);
443 		return NULL;
444 	}
445 
446 	return data;
447 }
448 
449 #endif
450 
wps_oob_use_cred(struct wps_context * wps,struct wps_parse_attr * attr)451 int wps_oob_use_cred(struct wps_context *wps, struct wps_parse_attr *attr)
452 {
453 	struct wpabuf msg;
454 	size_t i;
455 
456 	for (i = 0; i < attr->num_cred; i++) {
457 		struct wps_credential local_cred;
458 		struct wps_parse_attr cattr;
459 
460 		os_memset(&local_cred, 0, sizeof(local_cred));
461 		wpabuf_set(&msg, attr->cred[i], attr->cred_len[i]);
462 		if (wps_parse_msg(&msg, &cattr) < 0 ||
463 		    wps_process_cred(&cattr, &local_cred)) {
464 			wpa_printf(MSG_ERROR, "WPS: Failed to parse OOB "
465 				   "credential");
466 			return -1;
467 		}
468 		wps->cred_cb(wps->cb_ctx, &local_cred);
469 	}
470 
471 	return 0;
472 }
473 
474 
475 #endif /* CONFIG_WPS_OOB */
476 
477 
wps_dev_type_str2bin(const char * str,u8 dev_type[WPS_DEV_TYPE_LEN])478 int wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN])
479 {
480 	const char *pos;
481 
482 	/* <categ>-<OUI>-<subcateg> */
483 	WPA_PUT_BE16(dev_type, atoi(str));
484 	pos = os_strchr(str, '-');
485 	if (pos == NULL)
486 		return -1;
487 	pos++;
488 	if (hexstr2bin(pos, &dev_type[2], 4))
489 		return -1;
490 	pos = os_strchr(pos, '-');
491 	if (pos == NULL)
492 		return -1;
493 	pos++;
494 	WPA_PUT_BE16(&dev_type[6], atoi(pos));
495 
496 
497 	return 0;
498 }
499 
500 
wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN],char * buf,size_t buf_len)501 char * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf,
502 			    size_t buf_len)
503 {
504 	int ret;
505 
506 	ret = os_snprintf(buf, buf_len, "%u-%08X-%u",
507 			  WPA_GET_BE16(dev_type), WPA_GET_BE32(&dev_type[2]),
508 			  WPA_GET_BE16(&dev_type[6]));
509 	if (os_snprintf_error(buf_len, ret))
510 		return NULL;
511 
512 	return buf;
513 }
514 
515 
uuid_gen_mac_addr(const u8 * mac_addr,u8 * uuid)516 void uuid_gen_mac_addr(const u8 *mac_addr, u8 *uuid)
517 {
518 	const u8 *addr[2];
519 	size_t len[2];
520 	u8 hash[SHA1_MAC_LEN];
521 	u8 nsid[16] = {
522 		0x52, 0x64, 0x80, 0xf8,
523 		0xc9, 0x9b,
524 		0x4b, 0xe5,
525 		0xa6, 0x55,
526 		0x58, 0xed, 0x5f, 0x5d, 0x60, 0x84
527 	};
528 
529 	addr[0] = nsid;
530 	len[0] = sizeof(nsid);
531 	addr[1] = mac_addr;
532 	len[1] = 6;
533 	sha1_vector(2, addr, len, hash);
534 	os_memcpy(uuid, hash, 16);
535 
536 	/* Version: 5 = named-based version using SHA-1 */
537 	uuid[6] = (5 << 4) | (uuid[6] & 0x0f);
538 
539 	/* Variant specified in RFC 4122 */
540 	uuid[8] = 0x80 | (uuid[8] & 0x3f);
541 }
542 
543 
wps_config_methods_str2bin(const char * str)544 u16 wps_config_methods_str2bin(const char *str)
545 {
546 	u16 methods = 0;
547 
548 	if (str == NULL || str[0] == '\0') {
549 		/* Default to enabling methods based on build configuration */
550 		methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD;
551 		methods |= WPS_CONFIG_VIRT_DISPLAY;
552 #ifdef CONFIG_WPS_NFC
553 		methods |= WPS_CONFIG_NFC_INTERFACE;
554 #endif /* CONFIG_WPS_NFC */
555 #ifdef CONFIG_P2P
556 		methods |= WPS_CONFIG_P2PS;
557 #endif /* CONFIG_P2P */
558 	} else {
559 		if (os_strstr(str, "ethernet"))
560 			methods |= WPS_CONFIG_ETHERNET;
561 		if (os_strstr(str, "label"))
562 			methods |= WPS_CONFIG_LABEL;
563 		if (os_strstr(str, "display"))
564 			methods |= WPS_CONFIG_DISPLAY;
565 		if (os_strstr(str, "ext_nfc_token"))
566 			methods |= WPS_CONFIG_EXT_NFC_TOKEN;
567 		if (os_strstr(str, "int_nfc_token"))
568 			methods |= WPS_CONFIG_INT_NFC_TOKEN;
569 		if (os_strstr(str, "nfc_interface"))
570 			methods |= WPS_CONFIG_NFC_INTERFACE;
571 		if (os_strstr(str, "push_button"))
572 			methods |= WPS_CONFIG_PUSHBUTTON;
573 		if (os_strstr(str, "keypad"))
574 			methods |= WPS_CONFIG_KEYPAD;
575 		if (os_strstr(str, "virtual_display"))
576 			methods |= WPS_CONFIG_VIRT_DISPLAY;
577 		if (os_strstr(str, "physical_display"))
578 			methods |= WPS_CONFIG_PHY_DISPLAY;
579 		if (os_strstr(str, "virtual_push_button"))
580 			methods |= WPS_CONFIG_VIRT_PUSHBUTTON;
581 		if (os_strstr(str, "physical_push_button"))
582 			methods |= WPS_CONFIG_PHY_PUSHBUTTON;
583 		if (os_strstr(str, "p2ps"))
584 			methods |= WPS_CONFIG_P2PS;
585 	}
586 
587 	return methods;
588 }
589 
590 
wps_build_wsc_ack(struct wps_data * wps)591 struct wpabuf * wps_build_wsc_ack(struct wps_data *wps)
592 {
593 	struct wpabuf *msg;
594 
595 	wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_ACK");
596 
597 	msg = wpabuf_alloc(1000);
598 	if (msg == NULL)
599 		return NULL;
600 
601 	if (wps_build_version(msg) ||
602 	    wps_build_msg_type(msg, WPS_WSC_ACK) ||
603 	    wps_build_enrollee_nonce(wps, msg) ||
604 	    wps_build_registrar_nonce(wps, msg) ||
605 	    wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
606 		wpabuf_free(msg);
607 		return NULL;
608 	}
609 
610 	return msg;
611 }
612 
613 
wps_build_wsc_nack(struct wps_data * wps)614 struct wpabuf * wps_build_wsc_nack(struct wps_data *wps)
615 {
616 	struct wpabuf *msg;
617 
618 	wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_NACK");
619 
620 	msg = wpabuf_alloc(1000);
621 	if (msg == NULL)
622 		return NULL;
623 
624 	if (wps_build_version(msg) ||
625 	    wps_build_msg_type(msg, WPS_WSC_NACK) ||
626 	    wps_build_enrollee_nonce(wps, msg) ||
627 	    wps_build_registrar_nonce(wps, msg) ||
628 	    wps_build_config_error(msg, wps->config_error) ||
629 	    wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
630 		wpabuf_free(msg);
631 		return NULL;
632 	}
633 
634 	return msg;
635 }
636 
637 
638 #ifdef CONFIG_WPS_NFC
639 
wps_nfc_token_build(int ndef,int id,struct wpabuf * pubkey,struct wpabuf * dev_pw)640 struct wpabuf * wps_nfc_token_build(int ndef, int id, struct wpabuf *pubkey,
641 				    struct wpabuf *dev_pw)
642 {
643 	struct wpabuf *ret;
644 
645 	if (pubkey == NULL || dev_pw == NULL)
646 		return NULL;
647 
648 	ret = wps_build_nfc_pw_token(id, pubkey, dev_pw);
649 	if (ndef && ret) {
650 		struct wpabuf *tmp;
651 		tmp = ndef_build_wifi(ret);
652 		wpabuf_free(ret);
653 		if (tmp == NULL)
654 			return NULL;
655 		ret = tmp;
656 	}
657 
658 	return ret;
659 }
660 
661 
wps_nfc_gen_dh(struct wpabuf ** pubkey,struct wpabuf ** privkey)662 int wps_nfc_gen_dh(struct wpabuf **pubkey, struct wpabuf **privkey)
663 {
664 	struct wpabuf *priv = NULL, *pub = NULL;
665 	void *dh_ctx;
666 
667 	dh_ctx = dh5_init(&priv, &pub);
668 	if (dh_ctx == NULL)
669 		return -1;
670 	pub = wpabuf_zeropad(pub, 192);
671 	if (pub == NULL) {
672 		wpabuf_free(priv);
673 		dh5_free(dh_ctx);
674 		return -1;
675 	}
676 	wpa_hexdump_buf(MSG_DEBUG, "WPS: Generated new DH pubkey", pub);
677 	dh5_free(dh_ctx);
678 
679 	wpabuf_free(*pubkey);
680 	*pubkey = pub;
681 	wpabuf_clear_free(*privkey);
682 	*privkey = priv;
683 
684 	return 0;
685 }
686 
687 
wps_nfc_token_gen(int ndef,int * id,struct wpabuf ** pubkey,struct wpabuf ** privkey,struct wpabuf ** dev_pw)688 struct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey,
689 				  struct wpabuf **privkey,
690 				  struct wpabuf **dev_pw)
691 {
692 	struct wpabuf *pw;
693 	u16 val;
694 
695 	pw = wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN);
696 	if (pw == NULL)
697 		return NULL;
698 
699 	if (random_get_bytes(wpabuf_put(pw, WPS_OOB_DEVICE_PASSWORD_LEN),
700 			     WPS_OOB_DEVICE_PASSWORD_LEN) ||
701 	    random_get_bytes((u8 *) &val, sizeof(val))) {
702 		wpabuf_free(pw);
703 		return NULL;
704 	}
705 
706 	if (wps_nfc_gen_dh(pubkey, privkey) < 0) {
707 		wpabuf_free(pw);
708 		return NULL;
709 	}
710 
711 	*id = 0x10 + val % 0xfff0;
712 	wpabuf_clear_free(*dev_pw);
713 	*dev_pw = pw;
714 
715 	return wps_nfc_token_build(ndef, *id, *pubkey, *dev_pw);
716 }
717 
718 
wps_build_nfc_handover_req(struct wps_context * ctx,struct wpabuf * nfc_dh_pubkey)719 struct wpabuf * wps_build_nfc_handover_req(struct wps_context *ctx,
720 					   struct wpabuf *nfc_dh_pubkey)
721 {
722 	struct wpabuf *msg;
723 	void *len;
724 
725 	if (ctx == NULL)
726 		return NULL;
727 
728 	wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection "
729 		   "handover request");
730 
731 	if (nfc_dh_pubkey == NULL) {
732 		wpa_printf(MSG_DEBUG, "WPS: No NFC OOB Device Password "
733 			   "configured");
734 		return NULL;
735 	}
736 
737 	msg = wpabuf_alloc(1000);
738 	if (msg == NULL)
739 		return msg;
740 	len = wpabuf_put(msg, 2);
741 
742 	if (wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER,
743 				 nfc_dh_pubkey, NULL, 0) ||
744 	    wps_build_uuid_e(msg, ctx->uuid) ||
745 	    wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
746 		wpabuf_free(msg);
747 		return NULL;
748 	}
749 
750 	WPA_PUT_BE16(len, wpabuf_len(msg) - 2);
751 
752 	return msg;
753 }
754 
755 
wps_build_ssid(struct wpabuf * msg,struct wps_context * wps)756 static int wps_build_ssid(struct wpabuf *msg, struct wps_context *wps)
757 {
758 	wpa_printf(MSG_DEBUG, "WPS:  * SSID");
759 	wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID in Connection Handover Select",
760 			  wps->ssid, wps->ssid_len);
761 	wpabuf_put_be16(msg, ATTR_SSID);
762 	wpabuf_put_be16(msg, wps->ssid_len);
763 	wpabuf_put_data(msg, wps->ssid, wps->ssid_len);
764 	return 0;
765 }
766 
767 
wps_build_ap_freq(struct wpabuf * msg,int freq)768 static int wps_build_ap_freq(struct wpabuf *msg, int freq)
769 {
770 	enum hostapd_hw_mode mode;
771 	u8 channel, rf_band;
772 	u16 ap_channel;
773 
774 	if (freq <= 0)
775 		return 0;
776 
777 	mode = ieee80211_freq_to_chan(freq, &channel);
778 	if (mode == NUM_HOSTAPD_MODES)
779 		return 0; /* Unknown channel */
780 
781 	if (mode == HOSTAPD_MODE_IEEE80211G || mode == HOSTAPD_MODE_IEEE80211B)
782 		rf_band = WPS_RF_24GHZ;
783 	else if (mode == HOSTAPD_MODE_IEEE80211A)
784 		rf_band = WPS_RF_50GHZ;
785 	else if (mode == HOSTAPD_MODE_IEEE80211AD)
786 		rf_band = WPS_RF_60GHZ;
787 	else
788 		return 0; /* Unknown band */
789 	ap_channel = channel;
790 
791 	if (wps_build_rf_bands_attr(msg, rf_band) ||
792 	    wps_build_ap_channel(msg, ap_channel))
793 		return -1;
794 
795 	return 0;
796 }
797 
798 
wps_build_nfc_handover_sel(struct wps_context * ctx,struct wpabuf * nfc_dh_pubkey,const u8 * bssid,int freq)799 struct wpabuf * wps_build_nfc_handover_sel(struct wps_context *ctx,
800 					   struct wpabuf *nfc_dh_pubkey,
801 					   const u8 *bssid, int freq)
802 {
803 	struct wpabuf *msg;
804 	void *len;
805 
806 	if (ctx == NULL)
807 		return NULL;
808 
809 	wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection "
810 		   "handover select");
811 
812 	if (nfc_dh_pubkey == NULL) {
813 		wpa_printf(MSG_DEBUG, "WPS: No NFC OOB Device Password "
814 			   "configured");
815 		return NULL;
816 	}
817 
818 	msg = wpabuf_alloc(1000);
819 	if (msg == NULL)
820 		return msg;
821 	len = wpabuf_put(msg, 2);
822 
823 	if (wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER,
824 				 nfc_dh_pubkey, NULL, 0) ||
825 	    wps_build_ssid(msg, ctx) ||
826 	    wps_build_ap_freq(msg, freq) ||
827 	    (bssid && wps_build_mac_addr(msg, bssid)) ||
828 	    wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
829 		wpabuf_free(msg);
830 		return NULL;
831 	}
832 
833 	WPA_PUT_BE16(len, wpabuf_len(msg) - 2);
834 
835 	return msg;
836 }
837 
838 
wps_build_nfc_handover_req_p2p(struct wps_context * ctx,struct wpabuf * nfc_dh_pubkey)839 struct wpabuf * wps_build_nfc_handover_req_p2p(struct wps_context *ctx,
840 					       struct wpabuf *nfc_dh_pubkey)
841 {
842 	struct wpabuf *msg;
843 
844 	if (ctx == NULL)
845 		return NULL;
846 
847 	wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection "
848 		   "handover request (P2P)");
849 
850 	if (nfc_dh_pubkey == NULL) {
851 		wpa_printf(MSG_DEBUG, "WPS: No NFC DH Public Key configured");
852 		return NULL;
853 	}
854 
855 	msg = wpabuf_alloc(1000);
856 	if (msg == NULL)
857 		return msg;
858 
859 	if (wps_build_manufacturer(&ctx->dev, msg) ||
860 	    wps_build_model_name(&ctx->dev, msg) ||
861 	    wps_build_model_number(&ctx->dev, msg) ||
862 	    wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER,
863 				 nfc_dh_pubkey, NULL, 0) ||
864 	    wps_build_rf_bands(&ctx->dev, msg, 0) ||
865 	    wps_build_serial_number(&ctx->dev, msg) ||
866 	    wps_build_uuid_e(msg, ctx->uuid) ||
867 	    wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
868 		wpabuf_free(msg);
869 		return NULL;
870 	}
871 
872 	return msg;
873 }
874 
875 
wps_build_nfc_handover_sel_p2p(struct wps_context * ctx,int nfc_dev_pw_id,struct wpabuf * nfc_dh_pubkey,struct wpabuf * nfc_dev_pw)876 struct wpabuf * wps_build_nfc_handover_sel_p2p(struct wps_context *ctx,
877 					       int nfc_dev_pw_id,
878 					       struct wpabuf *nfc_dh_pubkey,
879 					       struct wpabuf *nfc_dev_pw)
880 {
881 	struct wpabuf *msg;
882 	const u8 *dev_pw;
883 	size_t dev_pw_len;
884 
885 	if (ctx == NULL)
886 		return NULL;
887 
888 	wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection "
889 		   "handover select (P2P)");
890 
891 	if (nfc_dh_pubkey == NULL ||
892 	    (nfc_dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER &&
893 	     nfc_dev_pw == NULL)) {
894 		wpa_printf(MSG_DEBUG, "WPS: No NFC OOB Device Password "
895 			   "configured");
896 		return NULL;
897 	}
898 
899 	msg = wpabuf_alloc(1000);
900 	if (msg == NULL)
901 		return msg;
902 
903 	if (nfc_dev_pw) {
904 		dev_pw = wpabuf_head(nfc_dev_pw);
905 		dev_pw_len = wpabuf_len(nfc_dev_pw);
906 	} else {
907 		dev_pw = NULL;
908 		dev_pw_len = 0;
909 	}
910 
911 	if (wps_build_manufacturer(&ctx->dev, msg) ||
912 	    wps_build_model_name(&ctx->dev, msg) ||
913 	    wps_build_model_number(&ctx->dev, msg) ||
914 	    wps_build_oob_dev_pw(msg, nfc_dev_pw_id, nfc_dh_pubkey,
915 				 dev_pw, dev_pw_len) ||
916 	    wps_build_rf_bands(&ctx->dev, msg, 0) ||
917 	    wps_build_serial_number(&ctx->dev, msg) ||
918 	    wps_build_uuid_e(msg, ctx->uuid) ||
919 	    wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
920 		wpabuf_free(msg);
921 		return NULL;
922 	}
923 
924 	return msg;
925 }
926 
927 #endif /* CONFIG_WPS_NFC */
928