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 (os_snprintf_error(buf_len, ret))
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#ifdef CONFIG_P2P
539		methods |= WPS_CONFIG_P2PS;
540#endif /* CONFIG_P2P */
541	} else {
542		if (os_strstr(str, "ethernet"))
543			methods |= WPS_CONFIG_ETHERNET;
544		if (os_strstr(str, "label"))
545			methods |= WPS_CONFIG_LABEL;
546		if (os_strstr(str, "display"))
547			methods |= WPS_CONFIG_DISPLAY;
548		if (os_strstr(str, "ext_nfc_token"))
549			methods |= WPS_CONFIG_EXT_NFC_TOKEN;
550		if (os_strstr(str, "int_nfc_token"))
551			methods |= WPS_CONFIG_INT_NFC_TOKEN;
552		if (os_strstr(str, "nfc_interface"))
553			methods |= WPS_CONFIG_NFC_INTERFACE;
554		if (os_strstr(str, "push_button"))
555			methods |= WPS_CONFIG_PUSHBUTTON;
556		if (os_strstr(str, "keypad"))
557			methods |= WPS_CONFIG_KEYPAD;
558		if (os_strstr(str, "virtual_display"))
559			methods |= WPS_CONFIG_VIRT_DISPLAY;
560		if (os_strstr(str, "physical_display"))
561			methods |= WPS_CONFIG_PHY_DISPLAY;
562		if (os_strstr(str, "virtual_push_button"))
563			methods |= WPS_CONFIG_VIRT_PUSHBUTTON;
564		if (os_strstr(str, "physical_push_button"))
565			methods |= WPS_CONFIG_PHY_PUSHBUTTON;
566		if (os_strstr(str, "p2ps"))
567			methods |= WPS_CONFIG_P2PS;
568	}
569
570	return methods;
571}
572
573
574struct wpabuf * wps_build_wsc_ack(struct wps_data *wps)
575{
576	struct wpabuf *msg;
577
578	wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_ACK");
579
580	msg = wpabuf_alloc(1000);
581	if (msg == NULL)
582		return NULL;
583
584	if (wps_build_version(msg) ||
585	    wps_build_msg_type(msg, WPS_WSC_ACK) ||
586	    wps_build_enrollee_nonce(wps, msg) ||
587	    wps_build_registrar_nonce(wps, msg) ||
588	    wps_build_wfa_ext(msg, 0, NULL, 0)) {
589		wpabuf_free(msg);
590		return NULL;
591	}
592
593	return msg;
594}
595
596
597struct wpabuf * wps_build_wsc_nack(struct wps_data *wps)
598{
599	struct wpabuf *msg;
600
601	wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_NACK");
602
603	msg = wpabuf_alloc(1000);
604	if (msg == NULL)
605		return NULL;
606
607	if (wps_build_version(msg) ||
608	    wps_build_msg_type(msg, WPS_WSC_NACK) ||
609	    wps_build_enrollee_nonce(wps, msg) ||
610	    wps_build_registrar_nonce(wps, msg) ||
611	    wps_build_config_error(msg, wps->config_error) ||
612	    wps_build_wfa_ext(msg, 0, NULL, 0)) {
613		wpabuf_free(msg);
614		return NULL;
615	}
616
617	return msg;
618}
619
620
621#ifdef CONFIG_WPS_NFC
622
623struct wpabuf * wps_nfc_token_build(int ndef, int id, struct wpabuf *pubkey,
624				    struct wpabuf *dev_pw)
625{
626	struct wpabuf *ret;
627
628	if (pubkey == NULL || dev_pw == NULL)
629		return NULL;
630
631	ret = wps_build_nfc_pw_token(id, pubkey, dev_pw);
632	if (ndef && ret) {
633		struct wpabuf *tmp;
634		tmp = ndef_build_wifi(ret);
635		wpabuf_free(ret);
636		if (tmp == NULL)
637			return NULL;
638		ret = tmp;
639	}
640
641	return ret;
642}
643
644
645int wps_nfc_gen_dh(struct wpabuf **pubkey, struct wpabuf **privkey)
646{
647	struct wpabuf *priv = NULL, *pub = NULL;
648	void *dh_ctx;
649
650	dh_ctx = dh5_init(&priv, &pub);
651	if (dh_ctx == NULL)
652		return -1;
653	pub = wpabuf_zeropad(pub, 192);
654	if (pub == NULL) {
655		wpabuf_free(priv);
656		return -1;
657	}
658	wpa_hexdump_buf(MSG_DEBUG, "WPS: Generated new DH pubkey", pub);
659	dh5_free(dh_ctx);
660
661	wpabuf_free(*pubkey);
662	*pubkey = pub;
663	wpabuf_free(*privkey);
664	*privkey = priv;
665
666	return 0;
667}
668
669
670struct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey,
671				  struct wpabuf **privkey,
672				  struct wpabuf **dev_pw)
673{
674	struct wpabuf *pw;
675	u16 val;
676
677	pw = wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN);
678	if (pw == NULL)
679		return NULL;
680
681	if (random_get_bytes(wpabuf_put(pw, WPS_OOB_DEVICE_PASSWORD_LEN),
682			     WPS_OOB_DEVICE_PASSWORD_LEN) ||
683	    random_get_bytes((u8 *) &val, sizeof(val))) {
684		wpabuf_free(pw);
685		return NULL;
686	}
687
688	if (wps_nfc_gen_dh(pubkey, privkey) < 0) {
689		wpabuf_free(pw);
690		return NULL;
691	}
692
693	*id = 0x10 + val % 0xfff0;
694	wpabuf_free(*dev_pw);
695	*dev_pw = pw;
696
697	return wps_nfc_token_build(ndef, *id, *pubkey, *dev_pw);
698}
699
700
701struct wpabuf * wps_build_nfc_handover_req(struct wps_context *ctx,
702					   struct wpabuf *nfc_dh_pubkey)
703{
704	struct wpabuf *msg;
705	void *len;
706
707	if (ctx == NULL)
708		return NULL;
709
710	wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection "
711		   "handover request");
712
713	if (nfc_dh_pubkey == NULL) {
714		wpa_printf(MSG_DEBUG, "WPS: No NFC OOB Device Password "
715			   "configured");
716		return NULL;
717	}
718
719	msg = wpabuf_alloc(1000);
720	if (msg == NULL)
721		return msg;
722	len = wpabuf_put(msg, 2);
723
724	if (wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER,
725				 nfc_dh_pubkey, NULL, 0) ||
726	    wps_build_uuid_e(msg, ctx->uuid) ||
727	    wps_build_wfa_ext(msg, 0, NULL, 0)) {
728		wpabuf_free(msg);
729		return NULL;
730	}
731
732	WPA_PUT_BE16(len, wpabuf_len(msg) - 2);
733
734	return msg;
735}
736
737
738static int wps_build_ssid(struct wpabuf *msg, struct wps_context *wps)
739{
740	wpa_printf(MSG_DEBUG, "WPS:  * SSID");
741	wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID in Connection Handover Select",
742			  wps->ssid, wps->ssid_len);
743	wpabuf_put_be16(msg, ATTR_SSID);
744	wpabuf_put_be16(msg, wps->ssid_len);
745	wpabuf_put_data(msg, wps->ssid, wps->ssid_len);
746	return 0;
747}
748
749
750static int wps_build_ap_freq(struct wpabuf *msg, int freq)
751{
752	enum hostapd_hw_mode mode;
753	u8 channel, rf_band;
754	u16 ap_channel;
755
756	if (freq <= 0)
757		return 0;
758
759	mode = ieee80211_freq_to_chan(freq, &channel);
760	if (mode == NUM_HOSTAPD_MODES)
761		return 0; /* Unknown channel */
762
763	if (mode == HOSTAPD_MODE_IEEE80211G || mode == HOSTAPD_MODE_IEEE80211B)
764		rf_band = WPS_RF_24GHZ;
765	else if (mode == HOSTAPD_MODE_IEEE80211A)
766		rf_band = WPS_RF_50GHZ;
767	else if (mode == HOSTAPD_MODE_IEEE80211AD)
768		rf_band = WPS_RF_60GHZ;
769	else
770		return 0; /* Unknown band */
771	ap_channel = channel;
772
773	if (wps_build_rf_bands_attr(msg, rf_band) ||
774	    wps_build_ap_channel(msg, ap_channel))
775		return -1;
776
777	return 0;
778}
779
780
781struct wpabuf * wps_build_nfc_handover_sel(struct wps_context *ctx,
782					   struct wpabuf *nfc_dh_pubkey,
783					   const u8 *bssid, int freq)
784{
785	struct wpabuf *msg;
786	void *len;
787
788	if (ctx == NULL)
789		return NULL;
790
791	wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection "
792		   "handover select");
793
794	if (nfc_dh_pubkey == NULL) {
795		wpa_printf(MSG_DEBUG, "WPS: No NFC OOB Device Password "
796			   "configured");
797		return NULL;
798	}
799
800	msg = wpabuf_alloc(1000);
801	if (msg == NULL)
802		return msg;
803	len = wpabuf_put(msg, 2);
804
805	if (wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER,
806				 nfc_dh_pubkey, NULL, 0) ||
807	    wps_build_ssid(msg, ctx) ||
808	    wps_build_ap_freq(msg, freq) ||
809	    (bssid && wps_build_mac_addr(msg, bssid)) ||
810	    wps_build_wfa_ext(msg, 0, NULL, 0)) {
811		wpabuf_free(msg);
812		return NULL;
813	}
814
815	WPA_PUT_BE16(len, wpabuf_len(msg) - 2);
816
817	return msg;
818}
819
820
821struct wpabuf * wps_build_nfc_handover_req_p2p(struct wps_context *ctx,
822					       struct wpabuf *nfc_dh_pubkey)
823{
824	struct wpabuf *msg;
825
826	if (ctx == NULL)
827		return NULL;
828
829	wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection "
830		   "handover request (P2P)");
831
832	if (nfc_dh_pubkey == NULL) {
833		wpa_printf(MSG_DEBUG, "WPS: No NFC DH Public Key configured");
834		return NULL;
835	}
836
837	msg = wpabuf_alloc(1000);
838	if (msg == NULL)
839		return msg;
840
841	if (wps_build_manufacturer(&ctx->dev, msg) ||
842	    wps_build_model_name(&ctx->dev, msg) ||
843	    wps_build_model_number(&ctx->dev, msg) ||
844	    wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER,
845				 nfc_dh_pubkey, NULL, 0) ||
846	    wps_build_rf_bands(&ctx->dev, msg, 0) ||
847	    wps_build_serial_number(&ctx->dev, msg) ||
848	    wps_build_uuid_e(msg, ctx->uuid) ||
849	    wps_build_wfa_ext(msg, 0, NULL, 0)) {
850		wpabuf_free(msg);
851		return NULL;
852	}
853
854	return msg;
855}
856
857
858struct wpabuf * wps_build_nfc_handover_sel_p2p(struct wps_context *ctx,
859					       int nfc_dev_pw_id,
860					       struct wpabuf *nfc_dh_pubkey,
861					       struct wpabuf *nfc_dev_pw)
862{
863	struct wpabuf *msg;
864	const u8 *dev_pw;
865	size_t dev_pw_len;
866
867	if (ctx == NULL)
868		return NULL;
869
870	wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection "
871		   "handover select (P2P)");
872
873	if (nfc_dh_pubkey == NULL ||
874	    (nfc_dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER &&
875	     nfc_dev_pw == NULL)) {
876		wpa_printf(MSG_DEBUG, "WPS: No NFC OOB Device Password "
877			   "configured");
878		return NULL;
879	}
880
881	msg = wpabuf_alloc(1000);
882	if (msg == NULL)
883		return msg;
884
885	if (nfc_dev_pw) {
886		dev_pw = wpabuf_head(nfc_dev_pw);
887		dev_pw_len = wpabuf_len(nfc_dev_pw);
888	} else {
889		dev_pw = NULL;
890		dev_pw_len = 0;
891	}
892
893	if (wps_build_manufacturer(&ctx->dev, msg) ||
894	    wps_build_model_name(&ctx->dev, msg) ||
895	    wps_build_model_number(&ctx->dev, msg) ||
896	    wps_build_oob_dev_pw(msg, nfc_dev_pw_id, nfc_dh_pubkey,
897				 dev_pw, dev_pw_len) ||
898	    wps_build_rf_bands(&ctx->dev, msg, 0) ||
899	    wps_build_serial_number(&ctx->dev, msg) ||
900	    wps_build_uuid_e(msg, ctx->uuid) ||
901	    wps_build_wfa_ext(msg, 0, NULL, 0)) {
902		wpabuf_free(msg);
903		return NULL;
904	}
905
906	return msg;
907}
908
909#endif /* CONFIG_WPS_NFC */
910