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