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