xref: /aosp_15_r20/external/wpa_supplicant_8/src/common/dpp.c (revision 03f9172ca588f91df233974f4258bab95191f931)
1 /*
2  * DPP functionality shared between hostapd and wpa_supplicant
3  * Copyright (c) 2017, Qualcomm Atheros, Inc.
4  * Copyright (c) 2018-2020, The Linux Foundation
5  * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
6  *
7  * This software may be distributed under the terms of the BSD license.
8  * See README for more details.
9  */
10 
11 #include "utils/includes.h"
12 
13 #include "utils/common.h"
14 #include "utils/base64.h"
15 #include "utils/json.h"
16 #include "utils/ip_addr.h"
17 #include "common/ieee802_11_common.h"
18 #include "common/wpa_ctrl.h"
19 #include "common/gas.h"
20 #include "eap_common/eap_defs.h"
21 #include "crypto/crypto.h"
22 #include "crypto/random.h"
23 #include "crypto/aes.h"
24 #include "crypto/aes_siv.h"
25 #include "drivers/driver.h"
26 #include "dpp.h"
27 #include "dpp_i.h"
28 
29 
30 #ifdef CONFIG_TESTING_OPTIONS
31 #ifdef CONFIG_DPP3
32 int dpp_version_override = 3;
33 #elif defined(CONFIG_DPP2)
34 int dpp_version_override = 2;
35 #else
36 int dpp_version_override = 1;
37 #endif
38 enum dpp_test_behavior dpp_test = DPP_TEST_DISABLED;
39 #endif /* CONFIG_TESTING_OPTIONS */
40 
41 
dpp_auth_fail(struct dpp_authentication * auth,const char * txt)42 void dpp_auth_fail(struct dpp_authentication *auth, const char *txt)
43 {
44 	wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "%s", txt);
45 }
46 
47 
dpp_alloc_msg(enum dpp_public_action_frame_type type,size_t len)48 struct wpabuf * dpp_alloc_msg(enum dpp_public_action_frame_type type,
49 			      size_t len)
50 {
51 	struct wpabuf *msg;
52 
53 	msg = wpabuf_alloc(8 + len);
54 	if (!msg)
55 		return NULL;
56 	wpabuf_put_u8(msg, WLAN_ACTION_PUBLIC);
57 	wpabuf_put_u8(msg, WLAN_PA_VENDOR_SPECIFIC);
58 	wpabuf_put_be24(msg, OUI_WFA);
59 	wpabuf_put_u8(msg, DPP_OUI_TYPE);
60 	wpabuf_put_u8(msg, 1); /* Crypto Suite */
61 	wpabuf_put_u8(msg, type);
62 	return msg;
63 }
64 
65 
dpp_get_attr(const u8 * buf,size_t len,u16 req_id,u16 * ret_len)66 const u8 * dpp_get_attr(const u8 *buf, size_t len, u16 req_id, u16 *ret_len)
67 {
68 	u16 id, alen;
69 	const u8 *pos = buf, *end = buf + len;
70 
71 	while (end - pos >= 4) {
72 		id = WPA_GET_LE16(pos);
73 		pos += 2;
74 		alen = WPA_GET_LE16(pos);
75 		pos += 2;
76 		if (alen > end - pos)
77 			return NULL;
78 		if (id == req_id) {
79 			*ret_len = alen;
80 			return pos;
81 		}
82 		pos += alen;
83 	}
84 
85 	return NULL;
86 }
87 
88 
dpp_get_attr_next(const u8 * prev,const u8 * buf,size_t len,u16 req_id,u16 * ret_len)89 static const u8 * dpp_get_attr_next(const u8 *prev, const u8 *buf, size_t len,
90 				    u16 req_id, u16 *ret_len)
91 {
92 	u16 id, alen;
93 	const u8 *pos, *end = buf + len;
94 
95 	if (!prev)
96 		pos = buf;
97 	else
98 		pos = prev + WPA_GET_LE16(prev - 2);
99 	while (end - pos >= 4) {
100 		id = WPA_GET_LE16(pos);
101 		pos += 2;
102 		alen = WPA_GET_LE16(pos);
103 		pos += 2;
104 		if (alen > end - pos)
105 			return NULL;
106 		if (id == req_id) {
107 			*ret_len = alen;
108 			return pos;
109 		}
110 		pos += alen;
111 	}
112 
113 	return NULL;
114 }
115 
116 
dpp_check_attrs(const u8 * buf,size_t len)117 int dpp_check_attrs(const u8 *buf, size_t len)
118 {
119 	const u8 *pos, *end;
120 	int wrapped_data = 0;
121 
122 	pos = buf;
123 	end = buf + len;
124 	while (end - pos >= 4) {
125 		u16 id, alen;
126 
127 		id = WPA_GET_LE16(pos);
128 		pos += 2;
129 		alen = WPA_GET_LE16(pos);
130 		pos += 2;
131 		wpa_printf(MSG_MSGDUMP, "DPP: Attribute ID %04x len %u",
132 			   id, alen);
133 		if (alen > end - pos) {
134 			wpa_printf(MSG_DEBUG,
135 				   "DPP: Truncated message - not enough room for the attribute - dropped");
136 			return -1;
137 		}
138 		if (wrapped_data) {
139 			wpa_printf(MSG_DEBUG,
140 				   "DPP: An unexpected attribute included after the Wrapped Data attribute");
141 			return -1;
142 		}
143 		if (id == DPP_ATTR_WRAPPED_DATA)
144 			wrapped_data = 1;
145 		pos += alen;
146 	}
147 
148 	if (end != pos) {
149 		wpa_printf(MSG_DEBUG,
150 			   "DPP: Unexpected octets (%d) after the last attribute",
151 			   (int) (end - pos));
152 		return -1;
153 	}
154 
155 	return 0;
156 }
157 
158 
dpp_bootstrap_info_free(struct dpp_bootstrap_info * info)159 void dpp_bootstrap_info_free(struct dpp_bootstrap_info *info)
160 {
161 	if (!info)
162 		return;
163 	os_free(info->uri);
164 	os_free(info->info);
165 	os_free(info->chan);
166 	os_free(info->host);
167 	os_free(info->pk);
168 	crypto_ec_key_deinit(info->pubkey);
169 	str_clear_free(info->configurator_params);
170 	os_free(info);
171 }
172 
173 
dpp_bootstrap_type_txt(enum dpp_bootstrap_type type)174 const char * dpp_bootstrap_type_txt(enum dpp_bootstrap_type type)
175 {
176 	switch (type) {
177 	case DPP_BOOTSTRAP_QR_CODE:
178 		return "QRCODE";
179 	case DPP_BOOTSTRAP_PKEX:
180 		return "PKEX";
181 	case DPP_BOOTSTRAP_NFC_URI:
182 		return "NFC-URI";
183 	}
184 	return "??";
185 }
186 
187 
dpp_uri_valid_info(const char * info)188 static int dpp_uri_valid_info(const char *info)
189 {
190 	while (*info) {
191 		unsigned char val = *info++;
192 
193 		if (val < 0x20 || val > 0x7e || val == 0x3b)
194 			return 0;
195 	}
196 
197 	return 1;
198 }
199 
200 
dpp_clone_uri(struct dpp_bootstrap_info * bi,const char * uri)201 static int dpp_clone_uri(struct dpp_bootstrap_info *bi, const char *uri)
202 {
203 	bi->uri = os_strdup(uri);
204 	return bi->uri ? 0 : -1;
205 }
206 
207 
dpp_parse_uri_chan_list(struct dpp_bootstrap_info * bi,const char * chan_list)208 int dpp_parse_uri_chan_list(struct dpp_bootstrap_info *bi,
209 			    const char *chan_list)
210 {
211 	const char *pos = chan_list, *pos2;
212 	int opclass = -1, channel, freq;
213 
214 	while (pos && *pos && *pos != ';') {
215 		pos2 = pos;
216 		while (*pos2 >= '0' && *pos2 <= '9')
217 			pos2++;
218 		if (*pos2 == '/') {
219 			opclass = atoi(pos);
220 			pos = pos2 + 1;
221 		}
222 		if (opclass <= 0)
223 			goto fail;
224 		channel = atoi(pos);
225 		if (channel <= 0)
226 			goto fail;
227 		while (*pos >= '0' && *pos <= '9')
228 			pos++;
229 		freq = ieee80211_chan_to_freq(NULL, opclass, channel);
230 		wpa_printf(MSG_DEBUG,
231 			   "DPP: URI channel-list: opclass=%d channel=%d ==> freq=%d",
232 			   opclass, channel, freq);
233 		bi->channels_listed = true;
234 		if (freq < 0) {
235 			wpa_printf(MSG_DEBUG,
236 				   "DPP: Ignore unknown URI channel-list channel (opclass=%d channel=%d)",
237 				   opclass, channel);
238 		} else if (bi->num_freq == DPP_BOOTSTRAP_MAX_FREQ) {
239 			wpa_printf(MSG_DEBUG,
240 				   "DPP: Too many channels in URI channel-list - ignore list");
241 			bi->num_freq = 0;
242 			break;
243 		} else {
244 			bi->freq[bi->num_freq++] = freq;
245 		}
246 
247 		if (*pos == ';' || *pos == '\0')
248 			break;
249 		if (*pos != ',')
250 			goto fail;
251 		pos++;
252 	}
253 
254 	return 0;
255 fail:
256 	wpa_printf(MSG_DEBUG, "DPP: Invalid URI channel-list");
257 	return -1;
258 }
259 
260 
dpp_parse_uri_mac(struct dpp_bootstrap_info * bi,const char * mac)261 int dpp_parse_uri_mac(struct dpp_bootstrap_info *bi, const char *mac)
262 {
263 	if (!mac)
264 		return 0;
265 
266 	if (hwaddr_aton2(mac, bi->mac_addr) < 0) {
267 		wpa_printf(MSG_DEBUG, "DPP: Invalid URI mac");
268 		return -1;
269 	}
270 
271 	wpa_printf(MSG_DEBUG, "DPP: URI mac: " MACSTR, MAC2STR(bi->mac_addr));
272 
273 	return 0;
274 }
275 
276 
dpp_parse_uri_info(struct dpp_bootstrap_info * bi,const char * info)277 int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info)
278 {
279 	const char *end;
280 
281 	if (!info)
282 		return 0;
283 
284 	end = os_strchr(info, ';');
285 	if (!end)
286 		end = info + os_strlen(info);
287 	bi->info = os_malloc(end - info + 1);
288 	if (!bi->info)
289 		return -1;
290 	os_memcpy(bi->info, info, end - info);
291 	bi->info[end - info] = '\0';
292 	wpa_printf(MSG_DEBUG, "DPP: URI(information): %s", bi->info);
293 	if (!dpp_uri_valid_info(bi->info)) {
294 		wpa_printf(MSG_DEBUG, "DPP: Invalid URI information payload");
295 		return -1;
296 	}
297 
298 	return 0;
299 }
300 
301 
dpp_parse_uri_version(struct dpp_bootstrap_info * bi,const char * version)302 int dpp_parse_uri_version(struct dpp_bootstrap_info *bi, const char *version)
303 {
304 #ifdef CONFIG_DPP2
305 	if (!version || DPP_VERSION < 2)
306 		return 0;
307 
308 	if (*version == '1')
309 		bi->version = 1;
310 	else if (*version == '2')
311 		bi->version = 2;
312 	else if (*version == '3')
313 		bi->version = 3;
314 	else
315 		wpa_printf(MSG_DEBUG, "DPP: Unknown URI version");
316 
317 	wpa_printf(MSG_DEBUG, "DPP: URI version: %d", bi->version);
318 #endif /* CONFIG_DPP2 */
319 
320 	return 0;
321 }
322 
323 
dpp_parse_uri_pk(struct dpp_bootstrap_info * bi,const char * info)324 static int dpp_parse_uri_pk(struct dpp_bootstrap_info *bi, const char *info)
325 {
326 	u8 *data;
327 	size_t data_len;
328 	int res;
329 	const char *end;
330 
331 	end = os_strchr(info, ';');
332 	if (!end)
333 		return -1;
334 
335 	data = base64_decode(info, end - info, &data_len);
336 	if (!data) {
337 		wpa_printf(MSG_DEBUG,
338 			   "DPP: Invalid base64 encoding on URI public-key");
339 		return -1;
340 	}
341 	wpa_hexdump(MSG_DEBUG, "DPP: Base64 decoded URI public-key",
342 		    data, data_len);
343 
344 	res = dpp_get_subject_public_key(bi, data, data_len);
345 	os_free(data);
346 	return res;
347 }
348 
349 
dpp_parse_uri_supported_curves(struct dpp_bootstrap_info * bi,const char * txt)350 static int dpp_parse_uri_supported_curves(struct dpp_bootstrap_info *bi,
351 					  const char *txt)
352 {
353 	int val;
354 
355 	if (!txt)
356 		return 0;
357 
358 	val = hex2num(txt[0]);
359 	if (val < 0)
360 		return -1;
361 	bi->supported_curves = val;
362 
363 	val = hex2num(txt[1]);
364 	if (val > 0)
365 		bi->supported_curves |= val << 4;
366 
367 	wpa_printf(MSG_DEBUG, "DPP: URI supported curves: 0x%x",
368 		   bi->supported_curves);
369 
370 	return 0;
371 }
372 
373 
dpp_parse_uri_host(struct dpp_bootstrap_info * bi,const char * txt)374 static int dpp_parse_uri_host(struct dpp_bootstrap_info *bi, const char *txt)
375 {
376 	const char *end;
377 	char *port;
378 	struct hostapd_ip_addr addr;
379 	char buf[100], *pos;
380 
381 	if (!txt)
382 		return 0;
383 
384 	end = os_strchr(txt, ';');
385 	if (!end)
386 		end = txt + os_strlen(txt);
387 	if (end - txt > (int) sizeof(buf) - 1)
388 		return -1;
389 	os_memcpy(buf, txt, end - txt);
390 	buf[end - txt] = '\0';
391 
392 	bi->port = DPP_TCP_PORT;
393 
394 	pos = buf;
395 	if (*pos == '[') {
396 		pos = &buf[1];
397 		port = os_strchr(pos, ']');
398 		if (!port)
399 			return -1;
400 		*port++ = '\0';
401 		if (*port == ':')
402 			bi->port = atoi(port + 1);
403 	}
404 
405 	if (hostapd_parse_ip_addr(pos, &addr) < 0) {
406 		if (buf[0] != '[') {
407 			port = os_strrchr(pos, ':');
408 			if (port) {
409 				*port++ = '\0';
410 				bi->port = atoi(port);
411 			}
412 		}
413 		if (hostapd_parse_ip_addr(pos, &addr) < 0) {
414 			wpa_printf(MSG_INFO,
415 				   "DPP: Invalid IP address in URI host entry: %s",
416 				   pos);
417 			return -1;
418 		}
419 	}
420 	os_free(bi->host);
421 	bi->host = os_memdup(&addr, sizeof(addr));
422 	if (!bi->host)
423 		return -1;
424 
425 	wpa_printf(MSG_DEBUG, "DPP: host: %s port: %u",
426 		   hostapd_ip_txt(bi->host, buf, sizeof(buf)), bi->port);
427 
428 	return 0;
429 }
430 
431 
dpp_parse_uri(const char * uri)432 static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri)
433 {
434 	const char *pos = uri;
435 	const char *end;
436 	const char *chan_list = NULL, *mac = NULL, *info = NULL, *pk = NULL;
437 	const char *version = NULL, *supported_curves = NULL, *host = NULL;
438 	struct dpp_bootstrap_info *bi;
439 
440 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: URI", uri, os_strlen(uri));
441 
442 	if (os_strncmp(pos, "DPP:", 4) != 0) {
443 		wpa_printf(MSG_INFO, "DPP: Not a DPP URI");
444 		return NULL;
445 	}
446 	pos += 4;
447 
448 	for (;;) {
449 		end = os_strchr(pos, ';');
450 		if (!end)
451 			break;
452 
453 		if (end == pos) {
454 			/* Handle terminating ";;" and ignore unexpected ";"
455 			 * for parsing robustness. */
456 			pos++;
457 			continue;
458 		}
459 
460 		if (pos[0] == 'C' && pos[1] == ':' && !chan_list)
461 			chan_list = pos + 2;
462 		else if (pos[0] == 'M' && pos[1] == ':' && !mac)
463 			mac = pos + 2;
464 		else if (pos[0] == 'I' && pos[1] == ':' && !info)
465 			info = pos + 2;
466 		else if (pos[0] == 'K' && pos[1] == ':' && !pk)
467 			pk = pos + 2;
468 		else if (pos[0] == 'V' && pos[1] == ':' && !version)
469 			version = pos + 2;
470 		else if (pos[0] == 'B' && pos[1] == ':' && !supported_curves)
471 			supported_curves = pos + 2;
472 		else if (pos[0] == 'H' && pos[1] == ':' && !host)
473 			host = pos + 2;
474 		else
475 			wpa_hexdump_ascii(MSG_DEBUG,
476 					  "DPP: Ignore unrecognized URI parameter",
477 					  pos, end - pos);
478 		pos = end + 1;
479 	}
480 
481 	if (!pk) {
482 		wpa_printf(MSG_INFO, "DPP: URI missing public-key");
483 		return NULL;
484 	}
485 
486 	bi = os_zalloc(sizeof(*bi));
487 	if (!bi)
488 		return NULL;
489 
490 	if (dpp_clone_uri(bi, uri) < 0 ||
491 	    dpp_parse_uri_chan_list(bi, chan_list) < 0 ||
492 	    dpp_parse_uri_mac(bi, mac) < 0 ||
493 	    dpp_parse_uri_info(bi, info) < 0 ||
494 	    dpp_parse_uri_version(bi, version) < 0 ||
495 	    dpp_parse_uri_supported_curves(bi, supported_curves) < 0 ||
496 	    dpp_parse_uri_host(bi, host) < 0 ||
497 	    dpp_parse_uri_pk(bi, pk) < 0) {
498 		dpp_bootstrap_info_free(bi);
499 		bi = NULL;
500 	}
501 
502 	return bi;
503 }
504 
505 
dpp_build_attr_status(struct wpabuf * msg,enum dpp_status_error status)506 void dpp_build_attr_status(struct wpabuf *msg, enum dpp_status_error status)
507 {
508 	wpa_printf(MSG_DEBUG, "DPP: Status %d", status);
509 	wpabuf_put_le16(msg, DPP_ATTR_STATUS);
510 	wpabuf_put_le16(msg, 1);
511 	wpabuf_put_u8(msg, status);
512 }
513 
514 
dpp_build_attr_r_bootstrap_key_hash(struct wpabuf * msg,const u8 * hash)515 void dpp_build_attr_r_bootstrap_key_hash(struct wpabuf *msg, const u8 *hash)
516 {
517 	if (hash) {
518 		wpa_printf(MSG_DEBUG, "DPP: R-Bootstrap Key Hash");
519 		wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH);
520 		wpabuf_put_le16(msg, SHA256_MAC_LEN);
521 		wpabuf_put_data(msg, hash, SHA256_MAC_LEN);
522 	}
523 }
524 
525 
dpp_channel_ok_init(struct hostapd_hw_modes * own_modes,u16 num_modes,unsigned int freq)526 static int dpp_channel_ok_init(struct hostapd_hw_modes *own_modes,
527 			       u16 num_modes, unsigned int freq)
528 {
529 	u16 m;
530 	int c, flag;
531 
532 	if (!own_modes || !num_modes)
533 		return 1;
534 
535 	for (m = 0; m < num_modes; m++) {
536 		for (c = 0; c < own_modes[m].num_channels; c++) {
537 			if ((unsigned int) own_modes[m].channels[c].freq !=
538 			    freq)
539 				continue;
540 			flag = own_modes[m].channels[c].flag;
541 			if (!(flag & (HOSTAPD_CHAN_DISABLED |
542 				      HOSTAPD_CHAN_NO_IR |
543 				      HOSTAPD_CHAN_RADAR)))
544 				return 1;
545 		}
546 	}
547 
548 	wpa_printf(MSG_DEBUG, "DPP: Peer channel %u MHz not supported", freq);
549 	return 0;
550 }
551 
552 
freq_included(const unsigned int freqs[],unsigned int num,unsigned int freq)553 static int freq_included(const unsigned int freqs[], unsigned int num,
554 			 unsigned int freq)
555 {
556 	while (num > 0) {
557 		if (freqs[--num] == freq)
558 			return 1;
559 	}
560 	return 0;
561 }
562 
563 
freq_to_start(unsigned int freqs[],unsigned int num,unsigned int freq)564 static void freq_to_start(unsigned int freqs[], unsigned int num,
565 			  unsigned int freq)
566 {
567 	unsigned int i;
568 
569 	for (i = 0; i < num; i++) {
570 		if (freqs[i] == freq)
571 			break;
572 	}
573 	if (i == 0 || i >= num)
574 		return;
575 	os_memmove(&freqs[1], &freqs[0], i * sizeof(freqs[0]));
576 	freqs[0] = freq;
577 }
578 
579 
dpp_channel_intersect(struct dpp_authentication * auth,struct hostapd_hw_modes * own_modes,u16 num_modes)580 static int dpp_channel_intersect(struct dpp_authentication *auth,
581 				 struct hostapd_hw_modes *own_modes,
582 				 u16 num_modes)
583 {
584 	struct dpp_bootstrap_info *peer_bi = auth->peer_bi;
585 	unsigned int i, freq;
586 
587 	for (i = 0; i < peer_bi->num_freq; i++) {
588 		freq = peer_bi->freq[i];
589 		if (freq_included(auth->freq, auth->num_freq, freq))
590 			continue;
591 		if (dpp_channel_ok_init(own_modes, num_modes, freq))
592 			auth->freq[auth->num_freq++] = freq;
593 	}
594 	if (!auth->num_freq) {
595 		wpa_printf(MSG_INFO,
596 			   "DPP: No available channels for initiating DPP Authentication");
597 		return -1;
598 	}
599 	auth->curr_freq = auth->freq[0];
600 	return 0;
601 }
602 
603 
dpp_channel_local_list(struct dpp_authentication * auth,struct hostapd_hw_modes * own_modes,u16 num_modes)604 static int dpp_channel_local_list(struct dpp_authentication *auth,
605 				  struct hostapd_hw_modes *own_modes,
606 				  u16 num_modes)
607 {
608 	u16 m;
609 	int c, flag;
610 	unsigned int freq;
611 
612 	auth->num_freq = 0;
613 
614 	if (!own_modes || !num_modes) {
615 		auth->freq[0] = 2412;
616 		auth->freq[1] = 2437;
617 		auth->freq[2] = 2462;
618 		auth->num_freq = 3;
619 		return 0;
620 	}
621 
622 	for (m = 0; m < num_modes; m++) {
623 		for (c = 0; c < own_modes[m].num_channels; c++) {
624 			freq = own_modes[m].channels[c].freq;
625 			flag = own_modes[m].channels[c].flag;
626 			if (flag & (HOSTAPD_CHAN_DISABLED |
627 				    HOSTAPD_CHAN_NO_IR |
628 				    HOSTAPD_CHAN_RADAR))
629 				continue;
630 			if (freq_included(auth->freq, auth->num_freq, freq))
631 				continue;
632 			auth->freq[auth->num_freq++] = freq;
633 			if (auth->num_freq == DPP_BOOTSTRAP_MAX_FREQ) {
634 				m = num_modes;
635 				break;
636 			}
637 		}
638 	}
639 
640 	return auth->num_freq == 0 ? -1 : 0;
641 }
642 
643 
dpp_prepare_channel_list(struct dpp_authentication * auth,unsigned int neg_freq,struct hostapd_hw_modes * own_modes,u16 num_modes)644 int dpp_prepare_channel_list(struct dpp_authentication *auth,
645 			     unsigned int neg_freq,
646 			     struct hostapd_hw_modes *own_modes, u16 num_modes)
647 {
648 	int res;
649 	char freqs[DPP_BOOTSTRAP_MAX_FREQ * 6 + 10], *pos, *end;
650 	unsigned int i;
651 
652 	if (!own_modes) {
653 		if (!neg_freq)
654 			return -1;
655 		auth->num_freq = 1;
656 		auth->freq[0] = neg_freq;
657 		auth->curr_freq = neg_freq;
658 		return 0;
659 	}
660 
661 	if (auth->peer_bi->num_freq > 0)
662 		res = dpp_channel_intersect(auth, own_modes, num_modes);
663 	else
664 		res = dpp_channel_local_list(auth, own_modes, num_modes);
665 	if (res < 0)
666 		return res;
667 
668 	/* Prioritize 2.4 GHz channels 6, 1, 11 (in this order) to hit the most
669 	 * likely channels first. */
670 	freq_to_start(auth->freq, auth->num_freq, 2462);
671 	freq_to_start(auth->freq, auth->num_freq, 2412);
672 	freq_to_start(auth->freq, auth->num_freq, 2437);
673 
674 	auth->freq_idx = 0;
675 	auth->curr_freq = auth->freq[0];
676 
677 	pos = freqs;
678 	end = pos + sizeof(freqs);
679 	for (i = 0; i < auth->num_freq; i++) {
680 		res = os_snprintf(pos, end - pos, " %u", auth->freq[i]);
681 		if (os_snprintf_error(end - pos, res))
682 			break;
683 		pos += res;
684 	}
685 	*pos = '\0';
686 	wpa_printf(MSG_DEBUG, "DPP: Possible frequencies for initiating:%s",
687 		   freqs);
688 
689 	return 0;
690 }
691 
692 
dpp_gen_uri(struct dpp_bootstrap_info * bi)693 int dpp_gen_uri(struct dpp_bootstrap_info *bi)
694 {
695 	char macstr[ETH_ALEN * 2 + 10];
696 	size_t len;
697 	char supp_curves[10];
698 	char host[100];
699 
700 	len = 4; /* "DPP:" */
701 	if (bi->chan)
702 		len += 3 + os_strlen(bi->chan); /* C:...; */
703 	if (is_zero_ether_addr(bi->mac_addr))
704 		macstr[0] = '\0';
705 	else
706 		os_snprintf(macstr, sizeof(macstr), "M:" COMPACT_MACSTR ";",
707 			    MAC2STR(bi->mac_addr));
708 	len += os_strlen(macstr); /* M:...; */
709 	if (bi->info)
710 		len += 3 + os_strlen(bi->info); /* I:...; */
711 #ifdef CONFIG_DPP2
712 	len += 4; /* V:2; */
713 #endif /* CONFIG_DPP2 */
714 	len += 4 + os_strlen(bi->pk); /* K:...;; */
715 
716 	if (bi->supported_curves) {
717 		u8 val = bi->supported_curves;
718 
719 		if (val & 0xf0) {
720 			val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
721 			len += os_snprintf(supp_curves, sizeof(supp_curves),
722 					   "B:%02x;", val);
723 		} else {
724 			len += os_snprintf(supp_curves, sizeof(supp_curves),
725 					   "B:%x;", val);
726 		}
727 	} else {
728 		supp_curves[0] = '\0';
729 	}
730 
731 	host[0] = '\0';
732 	if (bi->host) {
733 		char buf[100];
734 		const char *addr;
735 
736 		addr = hostapd_ip_txt(bi->host, buf, sizeof(buf));
737 		if (!addr)
738 			return -1;
739 		if (bi->port == DPP_TCP_PORT)
740 			len += os_snprintf(host, sizeof(host), "H:%s;", addr);
741 		else if (bi->host->af == AF_INET)
742 			len += os_snprintf(host, sizeof(host), "H:%s:%u;",
743 					   addr, bi->port);
744 		else
745 			len += os_snprintf(host, sizeof(host), "H:[%s]:%u;",
746 					   addr, bi->port);
747 	}
748 
749 	os_free(bi->uri);
750 	bi->uri = os_malloc(len + 1);
751 	if (!bi->uri)
752 		return -1;
753 	os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%s%s%s%sK:%s;;",
754 		    bi->chan ? "C:" : "", bi->chan ? bi->chan : "",
755 		    bi->chan ? ";" : "",
756 		    macstr,
757 		    bi->info ? "I:" : "", bi->info ? bi->info : "",
758 		    bi->info ? ";" : "",
759 		    DPP_VERSION == 3 ? "V:3;" :
760 		    (DPP_VERSION == 2 ? "V:2;" : ""),
761 		    supp_curves,
762 		    host,
763 		    bi->pk);
764 	return 0;
765 }
766 
767 
768 struct dpp_authentication *
dpp_alloc_auth(struct dpp_global * dpp,void * msg_ctx)769 dpp_alloc_auth(struct dpp_global *dpp, void *msg_ctx)
770 {
771 	struct dpp_authentication *auth;
772 
773 	auth = os_zalloc(sizeof(*auth));
774 	if (!auth)
775 		return NULL;
776 	auth->global = dpp;
777 	auth->msg_ctx = msg_ctx;
778 	auth->conf_resp_status = 255;
779 	return auth;
780 }
781 
782 
dpp_build_conf_req_attr(struct dpp_authentication * auth,const char * json)783 static struct wpabuf * dpp_build_conf_req_attr(struct dpp_authentication *auth,
784 					       const char *json)
785 {
786 	size_t nonce_len;
787 	size_t json_len, clear_len;
788 	struct wpabuf *clear = NULL, *msg = NULL, *pe = NULL;
789 	u8 *wrapped;
790 	size_t attr_len;
791 #ifdef CONFIG_DPP3
792 	u8 auth_i[DPP_MAX_HASH_LEN];
793 #endif /* CONFIG_DPP3 */
794 
795 	wpa_printf(MSG_DEBUG, "DPP: Build configuration request");
796 
797 	nonce_len = auth->curve->nonce_len;
798 	if (random_get_bytes(auth->e_nonce, nonce_len)) {
799 		wpa_printf(MSG_ERROR, "DPP: Failed to generate E-nonce");
800 		goto fail;
801 	}
802 	wpa_hexdump(MSG_DEBUG, "DPP: E-nonce", auth->e_nonce, nonce_len);
803 	json_len = os_strlen(json);
804 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: configRequest JSON", json, json_len);
805 
806 	/* { E-nonce, configAttrib }ke */
807 	clear_len = 4 + nonce_len + 4 + json_len;
808 #ifdef CONFIG_DPP3
809 	if (auth->waiting_new_key) {
810 		pe = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
811 		if (!pe)
812 			goto fail;
813 		clear_len += 4 + wpabuf_len(pe);
814 
815 		if (dpp_derive_auth_i(auth, auth_i) < 0)
816 			goto fail;
817 		clear_len += 4 + auth->curve->hash_len;
818 	}
819 #endif /* CONFIG_DPP3 */
820 	clear = wpabuf_alloc(clear_len);
821 	attr_len = 4 + clear_len + AES_BLOCK_SIZE;
822 #ifdef CONFIG_TESTING_OPTIONS
823 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_REQ)
824 		attr_len += 5;
825 #endif /* CONFIG_TESTING_OPTIONS */
826 	msg = wpabuf_alloc(attr_len);
827 	if (!clear || !msg)
828 		goto fail;
829 
830 #ifdef CONFIG_TESTING_OPTIONS
831 	if (dpp_test == DPP_TEST_NO_E_NONCE_CONF_REQ) {
832 		wpa_printf(MSG_INFO, "DPP: TESTING - no E-nonce");
833 		goto skip_e_nonce;
834 	}
835 	if (dpp_test == DPP_TEST_INVALID_E_NONCE_CONF_REQ) {
836 		wpa_printf(MSG_INFO, "DPP: TESTING - invalid E-nonce");
837 		wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
838 		wpabuf_put_le16(clear, nonce_len - 1);
839 		wpabuf_put_data(clear, auth->e_nonce, nonce_len - 1);
840 		goto skip_e_nonce;
841 	}
842 	if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_CONF_REQ) {
843 		wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
844 		goto skip_wrapped_data;
845 	}
846 #endif /* CONFIG_TESTING_OPTIONS */
847 
848 	/* E-nonce */
849 	wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
850 	wpabuf_put_le16(clear, nonce_len);
851 	wpabuf_put_data(clear, auth->e_nonce, nonce_len);
852 
853 #ifdef CONFIG_TESTING_OPTIONS
854 skip_e_nonce:
855 	if (dpp_test == DPP_TEST_NO_CONFIG_ATTR_OBJ_CONF_REQ) {
856 		wpa_printf(MSG_INFO, "DPP: TESTING - no configAttrib");
857 		goto skip_conf_attr_obj;
858 	}
859 #endif /* CONFIG_TESTING_OPTIONS */
860 
861 #ifdef CONFIG_DPP3
862 	if (pe) {
863 		wpa_printf(MSG_DEBUG, "DPP: Pe");
864 		wpabuf_put_le16(clear, DPP_ATTR_I_PROTOCOL_KEY);
865 		wpabuf_put_le16(clear, wpabuf_len(pe));
866 		wpabuf_put_buf(clear, pe);
867 	}
868 	if (auth->waiting_new_key) {
869 		wpa_printf(MSG_DEBUG, "DPP: Initiator Authentication Tag");
870 		wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG);
871 		wpabuf_put_le16(clear, auth->curve->hash_len);
872 		wpabuf_put_data(clear, auth_i, auth->curve->hash_len);
873 	}
874 #endif /* CONFIG_DPP3 */
875 
876 	/* configAttrib */
877 	wpabuf_put_le16(clear, DPP_ATTR_CONFIG_ATTR_OBJ);
878 	wpabuf_put_le16(clear, json_len);
879 	wpabuf_put_data(clear, json, json_len);
880 
881 #ifdef CONFIG_TESTING_OPTIONS
882 skip_conf_attr_obj:
883 #endif /* CONFIG_TESTING_OPTIONS */
884 
885 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
886 	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
887 	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
888 
889 	/* No AES-SIV AD */
890 	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
891 	if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
892 			    wpabuf_head(clear), wpabuf_len(clear),
893 			    0, NULL, NULL, wrapped) < 0)
894 		goto fail;
895 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
896 		    wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
897 
898 #ifdef CONFIG_TESTING_OPTIONS
899 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_REQ) {
900 		wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
901 		dpp_build_attr_status(msg, DPP_STATUS_OK);
902 	}
903 skip_wrapped_data:
904 #endif /* CONFIG_TESTING_OPTIONS */
905 
906 	wpa_hexdump_buf(MSG_DEBUG,
907 			"DPP: Configuration Request frame attributes", msg);
908 out:
909 	wpabuf_free(clear);
910 	wpabuf_free(pe);
911 	return msg;
912 
913 fail:
914 	wpabuf_free(msg);
915 	msg = NULL;
916 	goto out;
917 }
918 
919 
dpp_write_adv_proto(struct wpabuf * buf)920 void dpp_write_adv_proto(struct wpabuf *buf)
921 {
922 	/* Advertisement Protocol IE */
923 	wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO);
924 	wpabuf_put_u8(buf, 8); /* Length */
925 	wpabuf_put_u8(buf, 0x7f);
926 	wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
927 	wpabuf_put_u8(buf, 5);
928 	wpabuf_put_be24(buf, OUI_WFA);
929 	wpabuf_put_u8(buf, DPP_OUI_TYPE);
930 	wpabuf_put_u8(buf, 0x01);
931 }
932 
933 
dpp_write_gas_query(struct wpabuf * buf,struct wpabuf * query)934 void dpp_write_gas_query(struct wpabuf *buf, struct wpabuf *query)
935 {
936 	/* GAS Query */
937 	wpabuf_put_le16(buf, wpabuf_len(query));
938 	wpabuf_put_buf(buf, query);
939 }
940 
941 
dpp_build_conf_req(struct dpp_authentication * auth,const char * json)942 struct wpabuf * dpp_build_conf_req(struct dpp_authentication *auth,
943 				   const char *json)
944 {
945 	struct wpabuf *buf, *conf_req;
946 
947 	conf_req = dpp_build_conf_req_attr(auth, json);
948 	if (!conf_req) {
949 		wpa_printf(MSG_DEBUG,
950 			   "DPP: No configuration request data available");
951 		return NULL;
952 	}
953 
954 	buf = gas_build_initial_req(0, 10 + 2 + wpabuf_len(conf_req));
955 	if (!buf) {
956 		wpabuf_free(conf_req);
957 		return NULL;
958 	}
959 
960 	dpp_write_adv_proto(buf);
961 	dpp_write_gas_query(buf, conf_req);
962 	wpabuf_free(conf_req);
963 	wpa_hexdump_buf(MSG_MSGDUMP, "DPP: GAS Config Request", buf);
964 
965 	return buf;
966 }
967 
968 
dpp_build_conf_req_helper(struct dpp_authentication * auth,const char * name,enum dpp_netrole netrole,const char * mud_url,int * opclasses,const char * extra_name,const char * extra_value)969 struct wpabuf * dpp_build_conf_req_helper(struct dpp_authentication *auth,
970 					  const char *name,
971 					  enum dpp_netrole netrole,
972 					  const char *mud_url, int *opclasses,
973 					  const char *extra_name,
974 					  const char *extra_value)
975 {
976 	size_t len, name_len;
977 	const char *tech = "infra";
978 	const char *dpp_name;
979 	struct wpabuf *buf = NULL, *json = NULL;
980 	char *csr = NULL;
981 
982 #ifdef CONFIG_TESTING_OPTIONS
983 	if (dpp_test == DPP_TEST_INVALID_CONFIG_ATTR_OBJ_CONF_REQ) {
984 		static const char *bogus_tech = "knfra";
985 
986 		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Config Attr");
987 		tech = bogus_tech;
988 	}
989 #endif /* CONFIG_TESTING_OPTIONS */
990 
991 	dpp_name = name ? name : "Test";
992 	name_len = os_strlen(dpp_name);
993 
994 	len = 100 + name_len * 6 + 1 + int_array_len(opclasses) * 4;
995 	if (mud_url && mud_url[0])
996 		len += 10 + os_strlen(mud_url);
997 	if (extra_name && extra_value && extra_name[0] && extra_value[0])
998 		len += 10 + os_strlen(extra_name) + os_strlen(extra_value);
999 #ifdef CONFIG_DPP2
1000 	if (auth->csr) {
1001 		size_t csr_len;
1002 
1003 		csr = base64_encode_no_lf(wpabuf_head(auth->csr),
1004 					  wpabuf_len(auth->csr), &csr_len);
1005 		if (!csr)
1006 			goto fail;
1007 		len += 30 + csr_len;
1008 	}
1009 #endif /* CONFIG_DPP2 */
1010 	json = wpabuf_alloc(len);
1011 	if (!json)
1012 		goto fail;
1013 
1014 	json_start_object(json, NULL);
1015 	if (json_add_string_escape(json, "name", dpp_name, name_len) < 0)
1016 		goto fail;
1017 	json_value_sep(json);
1018 	json_add_string(json, "wi-fi_tech", tech);
1019 	json_value_sep(json);
1020 	json_add_string(json, "netRole", dpp_netrole_str(netrole));
1021 	if (mud_url && mud_url[0]) {
1022 		json_value_sep(json);
1023 		json_add_string(json, "mudurl", mud_url);
1024 	}
1025 	if (opclasses) {
1026 		int i;
1027 
1028 		json_value_sep(json);
1029 		json_start_array(json, "bandSupport");
1030 		for (i = 0; opclasses[i]; i++)
1031 			wpabuf_printf(json, "%s%u", i ? "," : "", opclasses[i]);
1032 		json_end_array(json);
1033 	}
1034 	if (csr) {
1035 		json_value_sep(json);
1036 		json_add_string(json, "pkcs10", csr);
1037 	}
1038 #ifdef CONFIG_DPP3
1039 	json_value_sep(json);
1040 	json_add_int(json, "capabilities", DPP_ENROLLEE_CAPAB_SAE_PW_ID);
1041 #endif /* CONFIG_DPP3 */
1042 	if (extra_name && extra_value && extra_name[0] && extra_value[0]) {
1043 		json_value_sep(json);
1044 		wpabuf_printf(json, "\"%s\":%s", extra_name, extra_value);
1045 	}
1046 	json_end_object(json);
1047 
1048 	buf = dpp_build_conf_req(auth, wpabuf_head(json));
1049 fail:
1050 	wpabuf_free(json);
1051 	os_free(csr);
1052 
1053 	return buf;
1054 }
1055 
1056 
bin_str_eq(const char * val,size_t len,const char * cmp)1057 static int bin_str_eq(const char *val, size_t len, const char *cmp)
1058 {
1059 	return os_strlen(cmp) == len && os_memcmp(val, cmp, len) == 0;
1060 }
1061 
1062 
dpp_configuration_alloc(const char * type)1063 struct dpp_configuration * dpp_configuration_alloc(const char *type)
1064 {
1065 	struct dpp_configuration *conf;
1066 	const char *end;
1067 	size_t len;
1068 
1069 	conf = os_zalloc(sizeof(*conf));
1070 	if (!conf)
1071 		goto fail;
1072 
1073 	end = os_strchr(type, ' ');
1074 	if (end)
1075 		len = end - type;
1076 	else
1077 		len = os_strlen(type);
1078 
1079 	if (bin_str_eq(type, len, "psk"))
1080 		conf->akm = DPP_AKM_PSK;
1081 	else if (bin_str_eq(type, len, "sae"))
1082 		conf->akm = DPP_AKM_SAE;
1083 	else if (bin_str_eq(type, len, "psk-sae") ||
1084 		 bin_str_eq(type, len, "psk+sae"))
1085 		conf->akm = DPP_AKM_PSK_SAE;
1086 	else if (bin_str_eq(type, len, "sae-dpp") ||
1087 		 bin_str_eq(type, len, "dpp+sae"))
1088 		conf->akm = DPP_AKM_SAE_DPP;
1089 	else if (bin_str_eq(type, len, "psk-sae-dpp") ||
1090 		 bin_str_eq(type, len, "dpp+psk+sae"))
1091 		conf->akm = DPP_AKM_PSK_SAE_DPP;
1092 	else if (bin_str_eq(type, len, "dpp"))
1093 		conf->akm = DPP_AKM_DPP;
1094 	else if (bin_str_eq(type, len, "dot1x"))
1095 		conf->akm = DPP_AKM_DOT1X;
1096 	else
1097 		goto fail;
1098 
1099 	return conf;
1100 fail:
1101 	dpp_configuration_free(conf);
1102 	return NULL;
1103 }
1104 
1105 
dpp_akm_psk(enum dpp_akm akm)1106 int dpp_akm_psk(enum dpp_akm akm)
1107 {
1108 	return akm == DPP_AKM_PSK || akm == DPP_AKM_PSK_SAE ||
1109 		akm == DPP_AKM_PSK_SAE_DPP;
1110 }
1111 
1112 
dpp_akm_sae(enum dpp_akm akm)1113 int dpp_akm_sae(enum dpp_akm akm)
1114 {
1115 	return akm == DPP_AKM_SAE || akm == DPP_AKM_PSK_SAE ||
1116 		akm == DPP_AKM_SAE_DPP || akm == DPP_AKM_PSK_SAE_DPP;
1117 }
1118 
1119 
dpp_akm_legacy(enum dpp_akm akm)1120 int dpp_akm_legacy(enum dpp_akm akm)
1121 {
1122 	return akm == DPP_AKM_PSK || akm == DPP_AKM_PSK_SAE ||
1123 		akm == DPP_AKM_SAE;
1124 }
1125 
1126 
dpp_akm_dpp(enum dpp_akm akm)1127 int dpp_akm_dpp(enum dpp_akm akm)
1128 {
1129 	return akm == DPP_AKM_DPP || akm == DPP_AKM_SAE_DPP ||
1130 		akm == DPP_AKM_PSK_SAE_DPP;
1131 }
1132 
1133 
dpp_akm_ver2(enum dpp_akm akm)1134 int dpp_akm_ver2(enum dpp_akm akm)
1135 {
1136 	return akm == DPP_AKM_SAE_DPP || akm == DPP_AKM_PSK_SAE_DPP;
1137 }
1138 
1139 
dpp_configuration_valid(const struct dpp_configuration * conf)1140 int dpp_configuration_valid(const struct dpp_configuration *conf)
1141 {
1142 	if (conf->ssid_len == 0)
1143 		return 0;
1144 	if (dpp_akm_psk(conf->akm) && !conf->passphrase && !conf->psk_set)
1145 		return 0;
1146 	if (dpp_akm_psk(conf->akm) && conf->passphrase) {
1147 		size_t len = os_strlen(conf->passphrase);
1148 
1149 		if (len > 63 || len < 8)
1150 			return 0;
1151 	}
1152 	if (dpp_akm_sae(conf->akm) && !conf->passphrase)
1153 		return 0;
1154 #ifdef CONFIG_DPP3
1155 	if (conf->idpass && (!conf->passphrase || !dpp_akm_sae(conf->akm)))
1156 		return 0;
1157 #endif /* CONFIG_DPP3 */
1158 	return 1;
1159 }
1160 
1161 
dpp_configuration_free(struct dpp_configuration * conf)1162 void dpp_configuration_free(struct dpp_configuration *conf)
1163 {
1164 	if (!conf)
1165 		return;
1166 	str_clear_free(conf->passphrase);
1167 #ifdef CONFIG_DPP3
1168 	os_free(conf->idpass);
1169 #endif /* CONFIG_DPP3 */
1170 	os_free(conf->group_id);
1171 	os_free(conf->csrattrs);
1172 	os_free(conf->extra_name);
1173 	os_free(conf->extra_value);
1174 	bin_clear_free(conf, sizeof(*conf));
1175 }
1176 
1177 
dpp_configuration_parse_helper(struct dpp_authentication * auth,const char * cmd,int idx)1178 static int dpp_configuration_parse_helper(struct dpp_authentication *auth,
1179 					  const char *cmd, int idx)
1180 {
1181 	const char *pos, *end;
1182 	struct dpp_configuration *conf_sta = NULL, *conf_ap = NULL;
1183 	struct dpp_configuration *conf = NULL;
1184 	size_t len;
1185 
1186 	pos = os_strstr(cmd, " conf=sta-");
1187 	if (pos) {
1188 		conf_sta = dpp_configuration_alloc(pos + 10);
1189 		if (!conf_sta)
1190 			goto fail;
1191 		conf_sta->netrole = DPP_NETROLE_STA;
1192 		conf = conf_sta;
1193 	}
1194 
1195 	pos = os_strstr(cmd, " conf=ap-");
1196 	if (pos) {
1197 		conf_ap = dpp_configuration_alloc(pos + 9);
1198 		if (!conf_ap)
1199 			goto fail;
1200 		conf_ap->netrole = DPP_NETROLE_AP;
1201 		conf = conf_ap;
1202 	}
1203 
1204 	pos = os_strstr(cmd, " conf=configurator");
1205 	if (pos)
1206 		auth->provision_configurator = 1;
1207 
1208 	if (!conf)
1209 		return 0;
1210 
1211 	pos = os_strstr(cmd, " ssid=");
1212 	if (pos) {
1213 		pos += 6;
1214 		end = os_strchr(pos, ' ');
1215 		conf->ssid_len = end ? (size_t) (end - pos) : os_strlen(pos);
1216 		conf->ssid_len /= 2;
1217 		if (conf->ssid_len > sizeof(conf->ssid) ||
1218 		    hexstr2bin(pos, conf->ssid, conf->ssid_len) < 0)
1219 			goto fail;
1220 	} else {
1221 #ifdef CONFIG_TESTING_OPTIONS
1222 		/* use a default SSID for legacy testing reasons */
1223 		os_memcpy(conf->ssid, "test", 4);
1224 		conf->ssid_len = 4;
1225 #else /* CONFIG_TESTING_OPTIONS */
1226 		goto fail;
1227 #endif /* CONFIG_TESTING_OPTIONS */
1228 	}
1229 
1230 	pos = os_strstr(cmd, " ssid_charset=");
1231 	if (pos) {
1232 		if (conf_ap) {
1233 			wpa_printf(MSG_INFO,
1234 				   "DPP: ssid64 option (ssid_charset param) not allowed for AP enrollee");
1235 			goto fail;
1236 		}
1237 		conf->ssid_charset = atoi(pos + 14);
1238 	}
1239 
1240 	pos = os_strstr(cmd, " pass=");
1241 	if (pos) {
1242 		size_t pass_len;
1243 
1244 		pos += 6;
1245 		end = os_strchr(pos, ' ');
1246 		pass_len = end ? (size_t) (end - pos) : os_strlen(pos);
1247 		pass_len /= 2;
1248 		conf->passphrase = os_zalloc(pass_len + 1);
1249 		if (!conf->passphrase ||
1250 		    hexstr2bin(pos, (u8 *) conf->passphrase, pass_len) < 0)
1251 			goto fail;
1252 	}
1253 
1254 #ifdef CONFIG_DPP3
1255 	pos = os_strstr(cmd, " idpass=");
1256 	if (pos) {
1257 		size_t idpass_len;
1258 
1259 		pos += 8;
1260 		end = os_strchr(pos, ' ');
1261 		idpass_len = end ? (size_t) (end - pos) : os_strlen(pos);
1262 		idpass_len /= 2;
1263 		conf->idpass = os_zalloc(idpass_len + 1);
1264 		if (!conf->idpass ||
1265 		    hexstr2bin(pos, (u8 *) conf->idpass, idpass_len) < 0)
1266 			goto fail;
1267 	}
1268 #endif /* CONFIG_DPP3 */
1269 
1270 	pos = os_strstr(cmd, " psk=");
1271 	if (pos) {
1272 		pos += 5;
1273 		if (hexstr2bin(pos, conf->psk, PMK_LEN) < 0)
1274 			goto fail;
1275 		conf->psk_set = 1;
1276 	}
1277 
1278 	pos = os_strstr(cmd, " group_id=");
1279 	if (pos) {
1280 		size_t group_id_len;
1281 
1282 		pos += 10;
1283 		end = os_strchr(pos, ' ');
1284 		group_id_len = end ? (size_t) (end - pos) : os_strlen(pos);
1285 		conf->group_id = os_malloc(group_id_len + 1);
1286 		if (!conf->group_id)
1287 			goto fail;
1288 		os_memcpy(conf->group_id, pos, group_id_len);
1289 		conf->group_id[group_id_len] = '\0';
1290 	}
1291 
1292 	pos = os_strstr(cmd, " expiry=");
1293 	if (pos) {
1294 		long int val;
1295 
1296 		pos += 8;
1297 		val = strtol(pos, NULL, 0);
1298 		if (val <= 0)
1299 			goto fail;
1300 		conf->netaccesskey_expiry = val;
1301 	}
1302 
1303 	pos = os_strstr(cmd, " csrattrs=");
1304 	if (pos) {
1305 		pos += 10;
1306 		end = os_strchr(pos, ' ');
1307 		len = end ? (size_t) (end - pos) : os_strlen(pos);
1308 		conf->csrattrs = os_zalloc(len + 1);
1309 		if (!conf->csrattrs)
1310 			goto fail;
1311 		os_memcpy(conf->csrattrs, pos, len);
1312 	}
1313 
1314 	pos = os_strstr(cmd, " conf_extra_name=");
1315 	if (pos) {
1316 		pos += 17;
1317 		end = os_strchr(pos, ' ');
1318 		len = end ? (size_t) (end - pos) : os_strlen(pos);
1319 		conf->extra_name = os_zalloc(len + 1);
1320 		if (!conf->extra_name)
1321 			goto fail;
1322 		os_memcpy(conf->extra_name, pos, len);
1323 	}
1324 
1325 	pos = os_strstr(cmd, " conf_extra_value=");
1326 	if (pos) {
1327 		pos += 18;
1328 		end = os_strchr(pos, ' ');
1329 		len = end ? (size_t) (end - pos) : os_strlen(pos);
1330 		len /= 2;
1331 		conf->extra_value = os_zalloc(len + 1);
1332 		if (!conf->extra_value ||
1333 		    hexstr2bin(pos, (u8 *) conf->extra_value, len) < 0)
1334 			goto fail;
1335 	}
1336 
1337 	if (!dpp_configuration_valid(conf))
1338 		goto fail;
1339 
1340 	if (idx == 0) {
1341 		auth->conf_sta = conf_sta;
1342 		auth->conf_ap = conf_ap;
1343 	} else if (idx == 1) {
1344 		if (!auth->conf_sta)
1345 			auth->conf_sta = conf_sta;
1346 		else
1347 			auth->conf2_sta = conf_sta;
1348 		if (!auth->conf_ap)
1349 			auth->conf_ap = conf_ap;
1350 		else
1351 			auth->conf2_ap = conf_ap;
1352 	} else {
1353 		goto fail;
1354 	}
1355 	return 0;
1356 
1357 fail:
1358 	dpp_configuration_free(conf_sta);
1359 	dpp_configuration_free(conf_ap);
1360 	return -1;
1361 }
1362 
1363 
dpp_configuration_parse(struct dpp_authentication * auth,const char * cmd)1364 static int dpp_configuration_parse(struct dpp_authentication *auth,
1365 				   const char *cmd)
1366 {
1367 	const char *pos;
1368 	char *tmp;
1369 	size_t len;
1370 	int res;
1371 
1372 	pos = os_strstr(cmd, " @CONF-OBJ-SEP@ ");
1373 	if (!pos)
1374 		return dpp_configuration_parse_helper(auth, cmd, 0);
1375 
1376 	len = pos - cmd;
1377 	tmp = os_malloc(len + 1);
1378 	if (!tmp)
1379 		goto fail;
1380 	os_memcpy(tmp, cmd, len);
1381 	tmp[len] = '\0';
1382 	res = dpp_configuration_parse_helper(auth, tmp, 0);
1383 	str_clear_free(tmp);
1384 	if (res)
1385 		goto fail;
1386 	res = dpp_configuration_parse_helper(auth, cmd + len, 1);
1387 	if (res)
1388 		goto fail;
1389 	return 0;
1390 fail:
1391 	dpp_configuration_free(auth->conf_sta);
1392 	dpp_configuration_free(auth->conf2_sta);
1393 	dpp_configuration_free(auth->conf_ap);
1394 	dpp_configuration_free(auth->conf2_ap);
1395 	return -1;
1396 }
1397 
1398 
1399 static struct dpp_configurator *
dpp_configurator_get_id(struct dpp_global * dpp,unsigned int id)1400 dpp_configurator_get_id(struct dpp_global *dpp, unsigned int id)
1401 {
1402 	struct dpp_configurator *conf;
1403 
1404 	if (!dpp)
1405 		return NULL;
1406 
1407 	dl_list_for_each(conf, &dpp->configurator,
1408 			 struct dpp_configurator, list) {
1409 		if (conf->id == id)
1410 			return conf;
1411 	}
1412 	return NULL;
1413 }
1414 
1415 
dpp_set_configurator(struct dpp_authentication * auth,const char * cmd)1416 int dpp_set_configurator(struct dpp_authentication *auth, const char *cmd)
1417 {
1418 	const char *pos;
1419 	char *tmp = NULL;
1420 	int ret = -1;
1421 
1422 	if (!cmd || auth->configurator_set)
1423 		return 0;
1424 	auth->configurator_set = 1;
1425 
1426 	if (cmd[0] != ' ') {
1427 		size_t len;
1428 
1429 		len = os_strlen(cmd);
1430 		tmp = os_malloc(len + 2);
1431 		if (!tmp)
1432 			goto fail;
1433 		tmp[0] = ' ';
1434 		os_memcpy(tmp + 1, cmd, len + 1);
1435 		cmd = tmp;
1436 	}
1437 
1438 	wpa_printf(MSG_DEBUG, "DPP: Set configurator parameters: %s", cmd);
1439 
1440 	if (os_strstr(cmd, " conf=query")) {
1441 		auth->configurator_set = 0;
1442 		auth->use_config_query = true;
1443 		ret = 0;
1444 		goto fail;
1445 	}
1446 
1447 	pos = os_strstr(cmd, " configurator=");
1448 	if (!auth->conf && pos) {
1449 		pos += 14;
1450 		auth->conf = dpp_configurator_get_id(auth->global, atoi(pos));
1451 		if (!auth->conf) {
1452 			wpa_printf(MSG_INFO,
1453 				   "DPP: Could not find the specified configurator");
1454 			goto fail;
1455 		}
1456 	}
1457 
1458 	pos = os_strstr(cmd, " conn_status=");
1459 	if (pos) {
1460 		pos += 13;
1461 		auth->send_conn_status = atoi(pos);
1462 	}
1463 
1464 	pos = os_strstr(cmd, " akm_use_selector=");
1465 	if (pos) {
1466 		pos += 18;
1467 		auth->akm_use_selector = atoi(pos);
1468 	}
1469 
1470 	if (dpp_configuration_parse(auth, cmd) < 0) {
1471 		wpa_msg(auth->msg_ctx, MSG_INFO,
1472 			"DPP: Failed to set configurator parameters");
1473 		goto fail;
1474 	}
1475 	ret = 0;
1476 fail:
1477 	os_free(tmp);
1478 	return ret;
1479 }
1480 
1481 
dpp_auth_deinit(struct dpp_authentication * auth)1482 void dpp_auth_deinit(struct dpp_authentication *auth)
1483 {
1484 	unsigned int i;
1485 
1486 	if (!auth)
1487 		return;
1488 	dpp_configuration_free(auth->conf_ap);
1489 	dpp_configuration_free(auth->conf2_ap);
1490 	dpp_configuration_free(auth->conf_sta);
1491 	dpp_configuration_free(auth->conf2_sta);
1492 	crypto_ec_key_deinit(auth->own_protocol_key);
1493 	crypto_ec_key_deinit(auth->peer_protocol_key);
1494 	crypto_ec_key_deinit(auth->reconfig_old_protocol_key);
1495 	wpabuf_free(auth->req_msg);
1496 	wpabuf_free(auth->resp_msg);
1497 	wpabuf_free(auth->conf_req);
1498 	wpabuf_free(auth->reconfig_req_msg);
1499 	wpabuf_free(auth->reconfig_resp_msg);
1500 	for (i = 0; i < auth->num_conf_obj; i++) {
1501 		struct dpp_config_obj *conf = &auth->conf_obj[i];
1502 
1503 		os_free(conf->connector);
1504 		wpabuf_free(conf->c_sign_key);
1505 		wpabuf_free(conf->certbag);
1506 		wpabuf_free(conf->certs);
1507 		wpabuf_free(conf->cacert);
1508 		os_free(conf->server_name);
1509 		wpabuf_free(conf->pp_key);
1510 	}
1511 #ifdef CONFIG_DPP2
1512 	dpp_free_asymmetric_key(auth->conf_key_pkg);
1513 	os_free(auth->csrattrs);
1514 	wpabuf_free(auth->csr);
1515 	wpabuf_free(auth->priv_key);
1516 	wpabuf_free(auth->cacert);
1517 	wpabuf_free(auth->certbag);
1518 	os_free(auth->trusted_eap_server_name);
1519 	wpabuf_free(auth->conf_resp_tcp);
1520 #endif /* CONFIG_DPP2 */
1521 	wpabuf_free(auth->net_access_key);
1522 	dpp_bootstrap_info_free(auth->tmp_own_bi);
1523 	if (auth->tmp_peer_bi) {
1524 		dl_list_del(&auth->tmp_peer_bi->list);
1525 		dpp_bootstrap_info_free(auth->tmp_peer_bi);
1526 	}
1527 	os_free(auth->e_name);
1528 	os_free(auth->e_mud_url);
1529 	os_free(auth->e_band_support);
1530 #ifdef CONFIG_TESTING_OPTIONS
1531 	os_free(auth->config_obj_override);
1532 	os_free(auth->discovery_override);
1533 	os_free(auth->groups_override);
1534 #endif /* CONFIG_TESTING_OPTIONS */
1535 	bin_clear_free(auth, sizeof(*auth));
1536 }
1537 
1538 
1539 static struct wpabuf *
dpp_build_conf_start(struct dpp_authentication * auth,struct dpp_configuration * conf,size_t tailroom)1540 dpp_build_conf_start(struct dpp_authentication *auth,
1541 		     struct dpp_configuration *conf, size_t tailroom)
1542 {
1543 	struct wpabuf *buf;
1544 
1545 #ifdef CONFIG_TESTING_OPTIONS
1546 	if (auth->discovery_override)
1547 		tailroom += os_strlen(auth->discovery_override);
1548 #endif /* CONFIG_TESTING_OPTIONS */
1549 
1550 	buf = wpabuf_alloc(200 + tailroom);
1551 	if (!buf)
1552 		return NULL;
1553 	json_start_object(buf, NULL);
1554 	json_add_string(buf, "wi-fi_tech", "infra");
1555 	json_value_sep(buf);
1556 #ifdef CONFIG_TESTING_OPTIONS
1557 	if (auth->discovery_override) {
1558 		wpa_printf(MSG_DEBUG, "DPP: TESTING - discovery override: '%s'",
1559 			   auth->discovery_override);
1560 		wpabuf_put_str(buf, "\"discovery\":");
1561 		wpabuf_put_str(buf, auth->discovery_override);
1562 		json_value_sep(buf);
1563 		return buf;
1564 	}
1565 #endif /* CONFIG_TESTING_OPTIONS */
1566 	json_start_object(buf, "discovery");
1567 	if (((!conf->ssid_charset || auth->peer_version < 2) &&
1568 	     json_add_string_escape(buf, "ssid", conf->ssid,
1569 				    conf->ssid_len) < 0) ||
1570 	    ((conf->ssid_charset && auth->peer_version >= 2) &&
1571 	     json_add_base64url(buf, "ssid64", conf->ssid,
1572 				conf->ssid_len) < 0)) {
1573 		wpabuf_free(buf);
1574 		return NULL;
1575 	}
1576 	if (conf->ssid_charset > 0) {
1577 		json_value_sep(buf);
1578 		json_add_int(buf, "ssid_charset", conf->ssid_charset);
1579 	}
1580 	json_end_object(buf);
1581 	json_value_sep(buf);
1582 
1583 	return buf;
1584 }
1585 
1586 
dpp_build_jwk(struct wpabuf * buf,const char * name,struct crypto_ec_key * key,const char * kid,const struct dpp_curve_params * curve)1587 int dpp_build_jwk(struct wpabuf *buf, const char *name,
1588 		  struct crypto_ec_key *key, const char *kid,
1589 		  const struct dpp_curve_params *curve)
1590 {
1591 	struct wpabuf *pub;
1592 	const u8 *pos;
1593 	int ret = -1;
1594 
1595 	pub = crypto_ec_key_get_pubkey_point(key, 0);
1596 	if (!pub)
1597 		goto fail;
1598 
1599 	json_start_object(buf, name);
1600 	json_add_string(buf, "kty", "EC");
1601 	json_value_sep(buf);
1602 	json_add_string(buf, "crv", curve->jwk_crv);
1603 	json_value_sep(buf);
1604 	pos = wpabuf_head(pub);
1605 	if (json_add_base64url(buf, "x", pos, curve->prime_len) < 0)
1606 		goto fail;
1607 	json_value_sep(buf);
1608 	pos += curve->prime_len;
1609 	if (json_add_base64url(buf, "y", pos, curve->prime_len) < 0)
1610 		goto fail;
1611 	if (kid) {
1612 		json_value_sep(buf);
1613 		json_add_string(buf, "kid", kid);
1614 	}
1615 	json_end_object(buf);
1616 	ret = 0;
1617 fail:
1618 	wpabuf_free(pub);
1619 	return ret;
1620 }
1621 
1622 
dpp_build_legacy_cred_params(struct wpabuf * buf,struct dpp_configuration * conf)1623 static void dpp_build_legacy_cred_params(struct wpabuf *buf,
1624 					 struct dpp_configuration *conf)
1625 {
1626 	if (conf->passphrase && os_strlen(conf->passphrase) < 64) {
1627 		json_add_string_escape(buf, "pass", conf->passphrase,
1628 				       os_strlen(conf->passphrase));
1629 #ifdef CONFIG_DPP3
1630 		if (conf->idpass) {
1631 			json_value_sep(buf);
1632 			json_add_string_escape(buf, "idpass", conf->idpass,
1633 					       os_strlen(conf->idpass));
1634 		}
1635 #endif /* CONFIG_DPP3 */
1636 	} else if (conf->psk_set) {
1637 		char psk[2 * sizeof(conf->psk) + 1];
1638 
1639 		wpa_snprintf_hex(psk, sizeof(psk),
1640 				 conf->psk, sizeof(conf->psk));
1641 		json_add_string(buf, "psk_hex", psk);
1642 		forced_memzero(psk, sizeof(psk));
1643 	}
1644 }
1645 
1646 
dpp_netrole_str(enum dpp_netrole netrole)1647 const char * dpp_netrole_str(enum dpp_netrole netrole)
1648 {
1649 	switch (netrole) {
1650 	case DPP_NETROLE_STA:
1651 		return "sta";
1652 	case DPP_NETROLE_AP:
1653 		return "ap";
1654 	case DPP_NETROLE_CONFIGURATOR:
1655 		return "configurator";
1656 	default:
1657 		return "??";
1658 	}
1659 }
1660 
1661 
dpp_supports_curve(const char * curve,struct dpp_bootstrap_info * bi)1662 static bool dpp_supports_curve(const char *curve, struct dpp_bootstrap_info *bi)
1663 {
1664 	enum dpp_bootstrap_supported_curves idx;
1665 
1666 	if (!bi || !bi->supported_curves)
1667 		return true; /* no support indication available */
1668 
1669 	if (os_strcmp(curve, "prime256v1") == 0)
1670 		idx = DPP_BOOTSTRAP_CURVE_P_256;
1671 	else if (os_strcmp(curve, "secp384r1") == 0)
1672 		idx = DPP_BOOTSTRAP_CURVE_P_384;
1673 	else if (os_strcmp(curve, "secp521r1") == 0)
1674 		idx = DPP_BOOTSTRAP_CURVE_P_521;
1675 	else if (os_strcmp(curve, "brainpoolP256r1") == 0)
1676 		idx = DPP_BOOTSTRAP_CURVE_BP_256;
1677 	else if (os_strcmp(curve, "brainpoolP384r1") == 0)
1678 		idx = DPP_BOOTSTRAP_CURVE_BP_384;
1679 	else if (os_strcmp(curve, "brainpoolP512r1") == 0)
1680 		idx = DPP_BOOTSTRAP_CURVE_BP_512;
1681 	else
1682 		return true;
1683 
1684 	return bi->supported_curves & BIT(idx);
1685 }
1686 
1687 
1688 static struct wpabuf *
dpp_build_conf_obj_dpp(struct dpp_authentication * auth,struct dpp_configuration * conf)1689 dpp_build_conf_obj_dpp(struct dpp_authentication *auth,
1690 		       struct dpp_configuration *conf)
1691 {
1692 	struct wpabuf *buf = NULL;
1693 	char *signed_conn = NULL;
1694 	size_t tailroom;
1695 	const struct dpp_curve_params *curve; /* C-sign-key curve */
1696 	const struct dpp_curve_params *nak_curve; /* netAccessKey curve */
1697 	struct wpabuf *dppcon = NULL;
1698 	size_t extra_len = 1000;
1699 	int incl_legacy;
1700 	enum dpp_akm akm;
1701 	const char *akm_str;
1702 
1703 	if (!auth->conf) {
1704 		wpa_printf(MSG_INFO,
1705 			   "DPP: No configurator specified - cannot generate DPP config object");
1706 		goto fail;
1707 	}
1708 	curve = auth->conf->curve;
1709 	if (dpp_akm_dpp(conf->akm) &&
1710 	    !dpp_supports_curve(curve->name, auth->peer_bi)) {
1711 		wpa_printf(MSG_DEBUG,
1712 			   "DPP: Enrollee does not support C-sign-key curve (%s) - cannot generate config object",
1713 			   curve->name);
1714 		goto fail;
1715 	}
1716 	if (auth->new_curve && auth->new_key_received)
1717 		nak_curve = auth->new_curve;
1718 	else
1719 		nak_curve = auth->curve;
1720 	if (!dpp_supports_curve(nak_curve->name, auth->peer_bi)) {
1721 		wpa_printf(MSG_DEBUG,
1722 			   "DPP: Enrollee does not support netAccessKey curve (%s) - cannot generate config object",
1723 			   nak_curve->name);
1724 		goto fail;
1725 	}
1726 
1727 	akm = conf->akm;
1728 	if (dpp_akm_ver2(akm) && auth->peer_version < 2) {
1729 		wpa_printf(MSG_DEBUG,
1730 			   "DPP: Convert DPP+legacy credential to DPP-only for peer that does not support version 2");
1731 		akm = DPP_AKM_DPP;
1732 	}
1733 
1734 #ifdef CONFIG_TESTING_OPTIONS
1735 	if (auth->groups_override)
1736 		extra_len += os_strlen(auth->groups_override);
1737 #endif /* CONFIG_TESTING_OPTIONS */
1738 
1739 	if (conf->group_id)
1740 		extra_len += os_strlen(conf->group_id);
1741 
1742 	/* Connector (JSON dppCon object) */
1743 	dppcon = wpabuf_alloc(extra_len + 2 * nak_curve->prime_len * 4 / 3);
1744 	if (!dppcon)
1745 		goto fail;
1746 #ifdef CONFIG_TESTING_OPTIONS
1747 	if (auth->groups_override) {
1748 		wpabuf_put_u8(dppcon, '{');
1749 		if (auth->groups_override) {
1750 			wpa_printf(MSG_DEBUG,
1751 				   "DPP: TESTING - groups override: '%s'",
1752 				   auth->groups_override);
1753 			wpabuf_put_str(dppcon, "\"groups\":");
1754 			wpabuf_put_str(dppcon, auth->groups_override);
1755 			json_value_sep(dppcon);
1756 		}
1757 		goto skip_groups;
1758 	}
1759 #endif /* CONFIG_TESTING_OPTIONS */
1760 	json_start_object(dppcon, NULL);
1761 	json_start_array(dppcon, "groups");
1762 	json_start_object(dppcon, NULL);
1763 	json_add_string(dppcon, "groupId",
1764 			conf->group_id ? conf->group_id : "*");
1765 	json_value_sep(dppcon);
1766 	json_add_string(dppcon, "netRole", dpp_netrole_str(conf->netrole));
1767 	json_end_object(dppcon);
1768 	json_end_array(dppcon);
1769 	json_value_sep(dppcon);
1770 #ifdef CONFIG_TESTING_OPTIONS
1771 skip_groups:
1772 #endif /* CONFIG_TESTING_OPTIONS */
1773 	if (!auth->peer_protocol_key) {
1774 		wpa_printf(MSG_DEBUG,
1775 			   "DPP: No peer protocol key available to build netAccessKey JWK");
1776 		goto fail;
1777 	}
1778 #ifdef CONFIG_DPP3
1779 	if (auth->conf->net_access_key_curve &&
1780 	    auth->curve != auth->conf->net_access_key_curve &&
1781 	    !auth->new_key_received) {
1782 		if (!dpp_supports_curve(auth->conf->net_access_key_curve->name,
1783 					auth->peer_bi)) {
1784 			wpa_printf(MSG_DEBUG,
1785 				   "DPP: Enrollee does not support the required netAccessKey curve (%s) - cannot generate config object",
1786 				   auth->conf->net_access_key_curve->name);
1787 			goto fail;
1788 		}
1789 		wpa_printf(MSG_DEBUG,
1790 			   "DPP: Peer protocol key curve (%s) does not match the required netAccessKey curve (%s) - %s",
1791 			   auth->curve->name,
1792 			   auth->conf->net_access_key_curve->name,
1793 			   auth->waiting_new_key ?
1794 			   "the required key not received" :
1795 			   "request a new key");
1796 		if (auth->waiting_new_key)
1797 			auth->waiting_new_key = false; /* failed */
1798 		else
1799 			auth->waiting_new_key = true;
1800 		goto fail;
1801 	}
1802 #endif /* CONFIG_DPP3 */
1803 	if (dpp_build_jwk(dppcon, "netAccessKey", auth->peer_protocol_key, NULL,
1804 			  nak_curve) < 0) {
1805 		wpa_printf(MSG_DEBUG, "DPP: Failed to build netAccessKey JWK");
1806 		goto fail;
1807 	}
1808 	if (conf->netaccesskey_expiry) {
1809 		struct os_tm tm;
1810 		char expiry[30];
1811 
1812 		if (os_gmtime(conf->netaccesskey_expiry, &tm) < 0) {
1813 			wpa_printf(MSG_DEBUG,
1814 				   "DPP: Failed to generate expiry string");
1815 			goto fail;
1816 		}
1817 		os_snprintf(expiry, sizeof(expiry),
1818 			    "%04u-%02u-%02uT%02u:%02u:%02uZ",
1819 			    tm.year, tm.month, tm.day,
1820 			    tm.hour, tm.min, tm.sec);
1821 		json_value_sep(dppcon);
1822 		json_add_string(dppcon, "expiry", expiry);
1823 	}
1824 #ifdef CONFIG_DPP3
1825 	json_value_sep(dppcon);
1826 	json_add_int(dppcon, "version", auth->peer_version);
1827 #endif /* CONFIG_DPP3 */
1828 	json_end_object(dppcon);
1829 	wpa_printf(MSG_DEBUG, "DPP: dppCon: %s",
1830 		   (const char *) wpabuf_head(dppcon));
1831 
1832 	signed_conn = dpp_sign_connector(auth->conf, dppcon);
1833 	if (!signed_conn)
1834 		goto fail;
1835 
1836 	incl_legacy = dpp_akm_psk(akm) || dpp_akm_sae(akm);
1837 	tailroom = 1000;
1838 	tailroom += 2 * curve->prime_len * 4 / 3 + os_strlen(auth->conf->kid);
1839 	tailroom += os_strlen(signed_conn);
1840 	if (incl_legacy)
1841 		tailroom += 1000;
1842 	if (akm == DPP_AKM_DOT1X) {
1843 		if (auth->certbag)
1844 			tailroom += 2 * wpabuf_len(auth->certbag);
1845 		if (auth->cacert)
1846 			tailroom += 2 * wpabuf_len(auth->cacert);
1847 		if (auth->trusted_eap_server_name)
1848 			tailroom += os_strlen(auth->trusted_eap_server_name);
1849 		tailroom += 1000;
1850 	}
1851 	if (conf->extra_name && conf->extra_value)
1852 		tailroom += 10 + os_strlen(conf->extra_name) +
1853 			os_strlen(conf->extra_value);
1854 	buf = dpp_build_conf_start(auth, conf, tailroom);
1855 	if (!buf)
1856 		goto fail;
1857 
1858 	if (auth->akm_use_selector && dpp_akm_ver2(akm))
1859 		akm_str = dpp_akm_selector_str(akm);
1860 	else
1861 		akm_str = dpp_akm_str(akm);
1862 	json_start_object(buf, "cred");
1863 	json_add_string(buf, "akm", akm_str);
1864 	json_value_sep(buf);
1865 	if (incl_legacy) {
1866 		dpp_build_legacy_cred_params(buf, conf);
1867 		json_value_sep(buf);
1868 	}
1869 	if (akm == DPP_AKM_DOT1X) {
1870 		json_start_object(buf, "entCreds");
1871 		if (!auth->certbag)
1872 			goto fail;
1873 		json_add_base64(buf, "certBag", wpabuf_head(auth->certbag),
1874 				wpabuf_len(auth->certbag));
1875 		if (auth->cacert) {
1876 			json_value_sep(buf);
1877 			json_add_base64(buf, "caCert",
1878 					wpabuf_head(auth->cacert),
1879 					wpabuf_len(auth->cacert));
1880 		}
1881 		if (auth->trusted_eap_server_name) {
1882 			json_value_sep(buf);
1883 			json_add_string(buf, "trustedEapServerName",
1884 					auth->trusted_eap_server_name);
1885 		}
1886 		json_value_sep(buf);
1887 		json_start_array(buf, "eapMethods");
1888 		wpabuf_printf(buf, "%d", EAP_TYPE_TLS);
1889 		json_end_array(buf);
1890 		json_end_object(buf);
1891 		json_value_sep(buf);
1892 	}
1893 	wpabuf_put_str(buf, "\"signedConnector\":\"");
1894 	wpabuf_put_str(buf, signed_conn);
1895 	wpabuf_put_str(buf, "\"");
1896 	json_value_sep(buf);
1897 	if (dpp_build_jwk(buf, "csign", auth->conf->csign, auth->conf->kid,
1898 			  curve) < 0) {
1899 		wpa_printf(MSG_DEBUG, "DPP: Failed to build csign JWK");
1900 		goto fail;
1901 	}
1902 #ifdef CONFIG_DPP2
1903 	if (auth->peer_version >= 2 && auth->conf->pp_key) {
1904 		json_value_sep(buf);
1905 		if (dpp_build_jwk(buf, "ppKey", auth->conf->pp_key, NULL,
1906 				  curve) < 0) {
1907 			wpa_printf(MSG_DEBUG, "DPP: Failed to build ppKey JWK");
1908 			goto fail;
1909 		}
1910 	}
1911 #endif /* CONFIG_DPP2 */
1912 
1913 	json_end_object(buf);
1914 	if (conf->extra_name && conf->extra_value) {
1915 		json_value_sep(buf);
1916 		wpabuf_printf(buf, "\"%s\":%s", conf->extra_name,
1917 			      conf->extra_value);
1918 	}
1919 	json_end_object(buf);
1920 
1921 	wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Configuration Object",
1922 			      wpabuf_head(buf), wpabuf_len(buf));
1923 
1924 #ifdef CONFIG_DPP3
1925 	if (!auth->conf->net_access_key_curve) {
1926 		/* All netAccessKey values used in the network will have to be
1927 		 * from the same curve for network introduction to work, so
1928 		 * hardcode the first used netAccessKey curve for consecutive
1929 		 * operations if there was no explicit configuration of which
1930 		 * curve to use. */
1931 		wpa_printf(MSG_DEBUG,
1932 			   "DPP: Update Configurator to require netAccessKey curve %s based on first provisioning",
1933 			   nak_curve->name);
1934 		auth->conf->net_access_key_curve = nak_curve;
1935 	}
1936 #endif /* CONFIG_DPP3 */
1937 
1938 out:
1939 	os_free(signed_conn);
1940 	wpabuf_free(dppcon);
1941 	return buf;
1942 fail:
1943 	wpa_printf(MSG_DEBUG, "DPP: Failed to build configuration object");
1944 	wpabuf_free(buf);
1945 	buf = NULL;
1946 	goto out;
1947 }
1948 
1949 
1950 static struct wpabuf *
dpp_build_conf_obj_legacy(struct dpp_authentication * auth,struct dpp_configuration * conf)1951 dpp_build_conf_obj_legacy(struct dpp_authentication *auth,
1952 			  struct dpp_configuration *conf)
1953 {
1954 	struct wpabuf *buf;
1955 	const char *akm_str;
1956 	size_t len = 1000;
1957 
1958 
1959 #ifdef CONFIG_DPP3
1960 	if (conf->idpass &&
1961 	    !(auth->enrollee_capabilities & DPP_ENROLLEE_CAPAB_SAE_PW_ID)) {
1962 		wpa_printf(MSG_DEBUG,
1963 			   "DPP: Enrollee does not support SAE Password Identifier - cannot generate config object");
1964 		return NULL;
1965 	}
1966 #endif /* CONFIG_DPP3 */
1967 
1968 	if (conf->extra_name && conf->extra_value)
1969 		len += 10 + os_strlen(conf->extra_name) +
1970 			os_strlen(conf->extra_value);
1971 	buf = dpp_build_conf_start(auth, conf, len);
1972 	if (!buf)
1973 		return NULL;
1974 
1975 	if (auth->akm_use_selector && dpp_akm_ver2(conf->akm))
1976 		akm_str = dpp_akm_selector_str(conf->akm);
1977 	else
1978 		akm_str = dpp_akm_str(conf->akm);
1979 	json_start_object(buf, "cred");
1980 	json_add_string(buf, "akm", akm_str);
1981 	json_value_sep(buf);
1982 	dpp_build_legacy_cred_params(buf, conf);
1983 	json_end_object(buf);
1984 	if (conf->extra_name && conf->extra_value) {
1985 		json_value_sep(buf);
1986 		wpabuf_printf(buf, "\"%s\":%s", conf->extra_name,
1987 			      conf->extra_value);
1988 	}
1989 	json_end_object(buf);
1990 
1991 	wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Configuration Object (legacy)",
1992 			      wpabuf_head(buf), wpabuf_len(buf));
1993 
1994 	return buf;
1995 }
1996 
1997 
dpp_get_peer_bi_id(struct dpp_authentication * auth)1998 static int dpp_get_peer_bi_id(struct dpp_authentication *auth)
1999 {
2000 	struct dpp_bootstrap_info *bi;
2001 
2002 	if (auth->peer_bi)
2003 		return auth->peer_bi->id;
2004 	if (auth->tmp_peer_bi)
2005 		return auth->tmp_peer_bi->id;
2006 
2007 	bi = os_zalloc(sizeof(*bi));
2008 	if (!bi)
2009 		return -1;
2010 	bi->id = dpp_next_id(auth->global);
2011 	dl_list_add(&auth->global->bootstrap, &bi->list);
2012 	auth->tmp_peer_bi = bi;
2013 	return bi->id;
2014 }
2015 
2016 
2017 static struct wpabuf *
dpp_build_conf_obj(struct dpp_authentication * auth,enum dpp_netrole netrole,int idx,bool cert_req)2018 dpp_build_conf_obj(struct dpp_authentication *auth, enum dpp_netrole netrole,
2019 		   int idx, bool cert_req)
2020 {
2021 	struct dpp_configuration *conf = NULL;
2022 
2023 #ifdef CONFIG_TESTING_OPTIONS
2024 	if (auth->config_obj_override) {
2025 		if (idx != 0)
2026 			return NULL;
2027 		wpa_printf(MSG_DEBUG, "DPP: Testing - Config Object override");
2028 		return wpabuf_alloc_copy(auth->config_obj_override,
2029 					 os_strlen(auth->config_obj_override));
2030 	}
2031 #endif /* CONFIG_TESTING_OPTIONS */
2032 
2033 	if (idx == 0) {
2034 		if (netrole == DPP_NETROLE_STA)
2035 			conf = auth->conf_sta;
2036 		else if (netrole == DPP_NETROLE_AP)
2037 			conf = auth->conf_ap;
2038 	} else if (idx == 1) {
2039 		if (netrole == DPP_NETROLE_STA)
2040 			conf = auth->conf2_sta;
2041 		else if (netrole == DPP_NETROLE_AP)
2042 			conf = auth->conf2_ap;
2043 	}
2044 	if (!conf) {
2045 		if (idx == 0) {
2046 			if (auth->use_config_query) {
2047 				wpa_printf(MSG_DEBUG,
2048 					   "DPP: No configuration available for Enrollee(%s) - waiting for configuration",
2049 					   dpp_netrole_str(netrole));
2050 				auth->waiting_config = true;
2051 				dpp_get_peer_bi_id(auth);
2052 				return NULL;
2053 			}
2054 			wpa_printf(MSG_DEBUG,
2055 				   "DPP: No configuration available for Enrollee(%s) - reject configuration request",
2056 				   dpp_netrole_str(netrole));
2057 		}
2058 		return NULL;
2059 	}
2060 
2061 	if (conf->akm == DPP_AKM_DOT1X) {
2062 		if (!auth->conf) {
2063 			wpa_printf(MSG_DEBUG,
2064 				   "DPP: No Configurator data available");
2065 			return NULL;
2066 		}
2067 		if (!cert_req && !auth->certbag) {
2068 			wpa_printf(MSG_DEBUG,
2069 				   "DPP: No certificate data available for dot1x configuration");
2070 			return NULL;
2071 		}
2072 		return dpp_build_conf_obj_dpp(auth, conf);
2073 	}
2074 	if (dpp_akm_dpp(conf->akm) || (auth->peer_version >= 2 && auth->conf))
2075 		return dpp_build_conf_obj_dpp(auth, conf);
2076 	return dpp_build_conf_obj_legacy(auth, conf);
2077 }
2078 
2079 
2080 struct wpabuf *
dpp_build_conf_resp(struct dpp_authentication * auth,const u8 * e_nonce,u16 e_nonce_len,enum dpp_netrole netrole,bool cert_req)2081 dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce,
2082 		    u16 e_nonce_len, enum dpp_netrole netrole, bool cert_req)
2083 {
2084 	struct wpabuf *conf = NULL, *conf2 = NULL, *env_data = NULL, *pc = NULL;
2085 	size_t clear_len, attr_len;
2086 	struct wpabuf *clear = NULL, *msg = NULL;
2087 	u8 *wrapped;
2088 	const u8 *addr[1];
2089 	size_t len[1];
2090 	enum dpp_status_error status;
2091 
2092 	if (auth->force_conf_resp_status != DPP_STATUS_OK) {
2093 		status = auth->force_conf_resp_status;
2094 		goto forced_status;
2095 	}
2096 
2097 	if (netrole == DPP_NETROLE_CONFIGURATOR) {
2098 #ifdef CONFIG_DPP2
2099 		env_data = dpp_build_enveloped_data(auth);
2100 #endif /* CONFIG_DPP2 */
2101 	} else {
2102 		conf = dpp_build_conf_obj(auth, netrole, 0, cert_req);
2103 		if (conf) {
2104 			wpa_hexdump_ascii(MSG_DEBUG,
2105 					  "DPP: configurationObject JSON",
2106 					  wpabuf_head(conf), wpabuf_len(conf));
2107 			conf2 = dpp_build_conf_obj(auth, netrole, 1, cert_req);
2108 		}
2109 	}
2110 
2111 	if (!conf && auth->waiting_config)
2112 		return NULL;
2113 	if (conf || env_data)
2114 		status = DPP_STATUS_OK;
2115 	else if (!cert_req && netrole == DPP_NETROLE_STA && auth->conf_sta &&
2116 		 auth->conf_sta->akm == DPP_AKM_DOT1X && !auth->waiting_csr)
2117 		status = DPP_STATUS_CSR_NEEDED;
2118 #ifdef CONFIG_DPP3
2119 	else if (auth->waiting_new_key)
2120 		status = DPP_STATUS_NEW_KEY_NEEDED;
2121 #endif /* CONFIG_DPP3 */
2122 	else
2123 		status = DPP_STATUS_CONFIGURE_FAILURE;
2124 forced_status:
2125 	auth->conf_resp_status = status;
2126 
2127 	/* { E-nonce, configurationObject[, sendConnStatus]}ke */
2128 	clear_len = 4 + e_nonce_len;
2129 	if (conf)
2130 		clear_len += 4 + wpabuf_len(conf);
2131 	if (conf2)
2132 		clear_len += 4 + wpabuf_len(conf2);
2133 	if (env_data)
2134 		clear_len += 4 + wpabuf_len(env_data);
2135 	if (auth->peer_version >= 2 && auth->send_conn_status &&
2136 	    netrole == DPP_NETROLE_STA)
2137 		clear_len += 4;
2138 	if (status == DPP_STATUS_CSR_NEEDED && auth->conf_sta &&
2139 	    auth->conf_sta->csrattrs)
2140 		clear_len += 4 + os_strlen(auth->conf_sta->csrattrs);
2141 #ifdef CONFIG_DPP3
2142 	if (status == DPP_STATUS_NEW_KEY_NEEDED) {
2143 		struct crypto_ec_key *new_pc;
2144 
2145 		clear_len += 6; /* Finite Cyclic Group attribute */
2146 
2147 		wpa_printf(MSG_DEBUG,
2148 			   "DPP: Generate a new own protocol key for the curve %s",
2149 			   auth->conf->net_access_key_curve->name);
2150 		new_pc = dpp_gen_keypair(auth->conf->net_access_key_curve);
2151 		if (!new_pc) {
2152 			wpa_printf(MSG_DEBUG, "DPP: Failed to generate new Pc");
2153 			return NULL;
2154 		}
2155 		pc = crypto_ec_key_get_pubkey_point(new_pc, 0);
2156 		if (!pc) {
2157 			crypto_ec_key_deinit(new_pc);
2158 			return NULL;
2159 		}
2160 		crypto_ec_key_deinit(auth->own_protocol_key);
2161 		auth->own_protocol_key = new_pc;
2162 		auth->new_curve = auth->conf->net_access_key_curve;
2163 		clear_len += 4 + wpabuf_len(pc);
2164 	}
2165 #endif /* CONFIG_DPP3 */
2166 	clear = wpabuf_alloc(clear_len);
2167 	attr_len = 4 + 1 + 4 + clear_len + AES_BLOCK_SIZE;
2168 #ifdef CONFIG_TESTING_OPTIONS
2169 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_RESP)
2170 		attr_len += 5;
2171 #endif /* CONFIG_TESTING_OPTIONS */
2172 	msg = wpabuf_alloc(attr_len);
2173 	if (!clear || !msg)
2174 		goto fail;
2175 
2176 #ifdef CONFIG_TESTING_OPTIONS
2177 	if (dpp_test == DPP_TEST_NO_E_NONCE_CONF_RESP) {
2178 		wpa_printf(MSG_INFO, "DPP: TESTING - no E-nonce");
2179 		goto skip_e_nonce;
2180 	}
2181 	if (dpp_test == DPP_TEST_E_NONCE_MISMATCH_CONF_RESP) {
2182 		wpa_printf(MSG_INFO, "DPP: TESTING - E-nonce mismatch");
2183 		wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
2184 		wpabuf_put_le16(clear, e_nonce_len);
2185 		wpabuf_put_data(clear, e_nonce, e_nonce_len - 1);
2186 		wpabuf_put_u8(clear, e_nonce[e_nonce_len - 1] ^ 0x01);
2187 		goto skip_e_nonce;
2188 	}
2189 	if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_CONF_RESP) {
2190 		wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
2191 		goto skip_wrapped_data;
2192 	}
2193 #endif /* CONFIG_TESTING_OPTIONS */
2194 
2195 	/* E-nonce */
2196 	wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
2197 	wpabuf_put_le16(clear, e_nonce_len);
2198 	wpabuf_put_data(clear, e_nonce, e_nonce_len);
2199 
2200 #ifdef CONFIG_TESTING_OPTIONS
2201 skip_e_nonce:
2202 	if (dpp_test == DPP_TEST_NO_CONFIG_OBJ_CONF_RESP) {
2203 		wpa_printf(MSG_INFO, "DPP: TESTING - Config Object");
2204 		goto skip_config_obj;
2205 	}
2206 #endif /* CONFIG_TESTING_OPTIONS */
2207 
2208 	if (conf) {
2209 		wpabuf_put_le16(clear, DPP_ATTR_CONFIG_OBJ);
2210 		wpabuf_put_le16(clear, wpabuf_len(conf));
2211 		wpabuf_put_buf(clear, conf);
2212 	}
2213 	if (auth->peer_version >= 2 && conf2) {
2214 		wpabuf_put_le16(clear, DPP_ATTR_CONFIG_OBJ);
2215 		wpabuf_put_le16(clear, wpabuf_len(conf2));
2216 		wpabuf_put_buf(clear, conf2);
2217 	} else if (conf2) {
2218 		wpa_printf(MSG_DEBUG,
2219 			   "DPP: Second Config Object available, but peer does not support more than one");
2220 	}
2221 	if (env_data) {
2222 		wpabuf_put_le16(clear, DPP_ATTR_ENVELOPED_DATA);
2223 		wpabuf_put_le16(clear, wpabuf_len(env_data));
2224 		wpabuf_put_buf(clear, env_data);
2225 	}
2226 
2227 	if (auth->peer_version >= 2 && auth->send_conn_status &&
2228 	    netrole == DPP_NETROLE_STA && status == DPP_STATUS_OK) {
2229 		wpa_printf(MSG_DEBUG, "DPP: sendConnStatus");
2230 		wpabuf_put_le16(clear, DPP_ATTR_SEND_CONN_STATUS);
2231 		wpabuf_put_le16(clear, 0);
2232 	}
2233 
2234 	if (status == DPP_STATUS_CSR_NEEDED && auth->conf_sta &&
2235 	    auth->conf_sta->csrattrs) {
2236 		auth->waiting_csr = true;
2237 		wpa_printf(MSG_DEBUG, "DPP: CSR Attributes Request");
2238 		wpabuf_put_le16(clear, DPP_ATTR_CSR_ATTR_REQ);
2239 		wpabuf_put_le16(clear, os_strlen(auth->conf_sta->csrattrs));
2240 		wpabuf_put_str(clear, auth->conf_sta->csrattrs);
2241 	}
2242 
2243 #ifdef CONFIG_DPP3
2244 	if (status == DPP_STATUS_NEW_KEY_NEEDED && auth->conf &&
2245 	    auth->conf->net_access_key_curve) {
2246 		u16 ike_group = auth->conf->net_access_key_curve->ike_group;
2247 
2248 		/* Finite Cyclic Group attribute */
2249 		wpa_printf(MSG_DEBUG, "DPP: Finite Cyclic Group: %u",
2250 			   ike_group);
2251 		wpabuf_put_le16(clear, DPP_ATTR_FINITE_CYCLIC_GROUP);
2252 		wpabuf_put_le16(clear, 2);
2253 		wpabuf_put_le16(clear, ike_group);
2254 
2255 		if (pc) {
2256 			wpa_printf(MSG_DEBUG, "DPP: Pc");
2257 			wpabuf_put_le16(clear, DPP_ATTR_R_PROTOCOL_KEY);
2258 			wpabuf_put_le16(clear, wpabuf_len(pc));
2259 			wpabuf_put_buf(clear, pc);
2260 		}
2261 	}
2262 #endif /* CONFIG_DPP3 */
2263 
2264 #ifdef CONFIG_TESTING_OPTIONS
2265 skip_config_obj:
2266 	if (dpp_test == DPP_TEST_NO_STATUS_CONF_RESP) {
2267 		wpa_printf(MSG_INFO, "DPP: TESTING - Status");
2268 		goto skip_status;
2269 	}
2270 	if (dpp_test == DPP_TEST_INVALID_STATUS_CONF_RESP) {
2271 		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
2272 		status = 255;
2273 	}
2274 #endif /* CONFIG_TESTING_OPTIONS */
2275 
2276 	/* DPP Status */
2277 	dpp_build_attr_status(msg, status);
2278 
2279 #ifdef CONFIG_TESTING_OPTIONS
2280 skip_status:
2281 #endif /* CONFIG_TESTING_OPTIONS */
2282 
2283 	addr[0] = wpabuf_head(msg);
2284 	len[0] = wpabuf_len(msg);
2285 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]);
2286 
2287 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
2288 	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
2289 	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
2290 
2291 	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
2292 	if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
2293 			    wpabuf_head(clear), wpabuf_len(clear),
2294 			    1, addr, len, wrapped) < 0)
2295 		goto fail;
2296 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
2297 		    wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
2298 
2299 #ifdef CONFIG_TESTING_OPTIONS
2300 	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_RESP) {
2301 		wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
2302 		dpp_build_attr_status(msg, DPP_STATUS_OK);
2303 	}
2304 skip_wrapped_data:
2305 #endif /* CONFIG_TESTING_OPTIONS */
2306 
2307 	wpa_hexdump_buf(MSG_DEBUG,
2308 			"DPP: Configuration Response attributes", msg);
2309 out:
2310 	wpabuf_clear_free(conf);
2311 	wpabuf_clear_free(conf2);
2312 	wpabuf_clear_free(env_data);
2313 	wpabuf_clear_free(clear);
2314 	wpabuf_free(pc);
2315 
2316 	return msg;
2317 fail:
2318 	wpabuf_free(msg);
2319 	msg = NULL;
2320 	goto out;
2321 }
2322 
2323 
2324 struct wpabuf *
dpp_conf_req_rx(struct dpp_authentication * auth,const u8 * attr_start,size_t attr_len)2325 dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
2326 		size_t attr_len)
2327 {
2328 	const u8 *wrapped_data, *e_nonce, *config_attr;
2329 	u16 wrapped_data_len, e_nonce_len, config_attr_len;
2330 	u8 *unwrapped = NULL;
2331 	size_t unwrapped_len = 0;
2332 	struct wpabuf *resp = NULL;
2333 	struct json_token *root = NULL, *token;
2334 	enum dpp_netrole netrole;
2335 	struct wpabuf *cert_req = NULL;
2336 #ifdef CONFIG_DPP3
2337 	const u8 *i_proto;
2338 	u16 i_proto_len;
2339 #endif /* CONFIG_DPP3 */
2340 
2341 #ifdef CONFIG_TESTING_OPTIONS
2342 	if (dpp_test == DPP_TEST_STOP_AT_CONF_REQ) {
2343 		wpa_printf(MSG_INFO,
2344 			   "DPP: TESTING - stop at Config Request");
2345 		return NULL;
2346 	}
2347 #endif /* CONFIG_TESTING_OPTIONS */
2348 
2349 	if (dpp_check_attrs(attr_start, attr_len) < 0) {
2350 		dpp_auth_fail(auth, "Invalid attribute in config request");
2351 		return NULL;
2352 	}
2353 
2354 	wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
2355 				    &wrapped_data_len);
2356 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
2357 		dpp_auth_fail(auth,
2358 			      "Missing or invalid required Wrapped Data attribute");
2359 		return NULL;
2360 	}
2361 
2362 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
2363 		    wrapped_data, wrapped_data_len);
2364 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
2365 	unwrapped = os_malloc(unwrapped_len);
2366 	if (!unwrapped)
2367 		return NULL;
2368 	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
2369 			    wrapped_data, wrapped_data_len,
2370 			    0, NULL, NULL, unwrapped) < 0) {
2371 		dpp_auth_fail(auth, "AES-SIV decryption failed");
2372 		goto fail;
2373 	}
2374 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
2375 		    unwrapped, unwrapped_len);
2376 
2377 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
2378 		dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
2379 		goto fail;
2380 	}
2381 
2382 	e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
2383 			       DPP_ATTR_ENROLLEE_NONCE,
2384 			       &e_nonce_len);
2385 	if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
2386 		dpp_auth_fail(auth,
2387 			      "Missing or invalid Enrollee Nonce attribute");
2388 		goto fail;
2389 	}
2390 	wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
2391 	os_memcpy(auth->e_nonce, e_nonce, e_nonce_len);
2392 
2393 #ifdef CONFIG_DPP3
2394 	i_proto = dpp_get_attr(unwrapped, unwrapped_len,
2395 			       DPP_ATTR_I_PROTOCOL_KEY, &i_proto_len);
2396 	if (i_proto && !auth->waiting_new_key) {
2397 		dpp_auth_fail(auth,
2398 			      "Enrollee included a new protocol key even though one was not expected");
2399 		goto fail;
2400 	}
2401 	if (i_proto) {
2402 		struct crypto_ec_key *pe;
2403 		u8 auth_i[DPP_MAX_HASH_LEN];
2404 		const u8 *rx_auth_i;
2405 		u16 rx_auth_i_len;
2406 
2407 		wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Protocol Key (new Pe)",
2408 			    i_proto, i_proto_len);
2409 
2410 		pe = dpp_set_pubkey_point(auth->own_protocol_key,
2411 					  i_proto, i_proto_len);
2412 		if (!pe) {
2413 			dpp_auth_fail(auth,
2414 				      "Invalid Initiator Protocol Key (Pe)");
2415 			goto fail;
2416 		}
2417 		dpp_debug_print_key("New Peer Protocol Key (Pe)", pe);
2418 		crypto_ec_key_deinit(auth->peer_protocol_key);
2419 		auth->peer_protocol_key = pe;
2420 		auth->new_key_received = true;
2421 		auth->waiting_new_key = false;
2422 
2423 		if (dpp_derive_auth_i(auth, auth_i) < 0)
2424 			goto fail;
2425 
2426 		rx_auth_i = dpp_get_attr(unwrapped, unwrapped_len,
2427 					 DPP_ATTR_I_AUTH_TAG, &rx_auth_i_len);
2428 		if (!rx_auth_i) {
2429 			dpp_auth_fail(auth,
2430 				      "Missing Initiator Authentication Tag");
2431 			goto fail;
2432 		}
2433 		if (rx_auth_i_len != auth->curve->hash_len ||
2434 		    os_memcmp(rx_auth_i, auth_i, auth->curve->hash_len) != 0) {
2435 			dpp_auth_fail(auth,
2436 				      "Mismatch in Initiator Authenticating Tag");
2437 			wpa_hexdump(MSG_DEBUG, "DPP: Received Auth-I",
2438 				    rx_auth_i, rx_auth_i_len);
2439 			wpa_hexdump(MSG_DEBUG, "DPP: Derived Auth-I'",
2440 				    auth_i, auth->curve->hash_len);
2441 			goto fail;
2442 		}
2443 	}
2444 #endif /* CONFIG_DPP3 */
2445 
2446 	config_attr = dpp_get_attr(unwrapped, unwrapped_len,
2447 				   DPP_ATTR_CONFIG_ATTR_OBJ,
2448 				   &config_attr_len);
2449 	if (!config_attr) {
2450 		dpp_auth_fail(auth,
2451 			      "Missing or invalid Config Attributes attribute");
2452 		goto fail;
2453 	}
2454 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: Config Attributes",
2455 			  config_attr, config_attr_len);
2456 
2457 	root = json_parse((const char *) config_attr, config_attr_len);
2458 	if (!root) {
2459 		dpp_auth_fail(auth, "Could not parse Config Attributes");
2460 		goto fail;
2461 	}
2462 
2463 	token = json_get_member(root, "name");
2464 	if (!token || token->type != JSON_STRING) {
2465 		dpp_auth_fail(auth, "No Config Attributes - name");
2466 		goto fail;
2467 	}
2468 	wpa_printf(MSG_DEBUG, "DPP: Enrollee name = '%s'", token->string);
2469 	os_free(auth->e_name);
2470 	auth->e_name = os_strdup(token->string);
2471 
2472 	token = json_get_member(root, "wi-fi_tech");
2473 	if (!token || token->type != JSON_STRING) {
2474 		dpp_auth_fail(auth, "No Config Attributes - wi-fi_tech");
2475 		goto fail;
2476 	}
2477 	wpa_printf(MSG_DEBUG, "DPP: wi-fi_tech = '%s'", token->string);
2478 	if (os_strcmp(token->string, "infra") != 0) {
2479 		wpa_printf(MSG_DEBUG, "DPP: Unsupported wi-fi_tech '%s'",
2480 			   token->string);
2481 		dpp_auth_fail(auth, "Unsupported wi-fi_tech");
2482 		goto fail;
2483 	}
2484 
2485 	token = json_get_member(root, "netRole");
2486 	if (!token || token->type != JSON_STRING) {
2487 		dpp_auth_fail(auth, "No Config Attributes - netRole");
2488 		goto fail;
2489 	}
2490 	wpa_printf(MSG_DEBUG, "DPP: netRole = '%s'", token->string);
2491 	if (os_strcmp(token->string, "sta") == 0) {
2492 		netrole = DPP_NETROLE_STA;
2493 	} else if (os_strcmp(token->string, "ap") == 0) {
2494 		netrole = DPP_NETROLE_AP;
2495 	} else if (os_strcmp(token->string, "configurator") == 0) {
2496 		netrole = DPP_NETROLE_CONFIGURATOR;
2497 	} else {
2498 		wpa_printf(MSG_DEBUG, "DPP: Unsupported netRole '%s'",
2499 			   token->string);
2500 		dpp_auth_fail(auth, "Unsupported netRole");
2501 		goto fail;
2502 	}
2503 	auth->e_netrole = netrole;
2504 
2505 	token = json_get_member(root, "mudurl");
2506 	if (token && token->type == JSON_STRING) {
2507 		wpa_printf(MSG_DEBUG, "DPP: mudurl = '%s'", token->string);
2508 		wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_MUD_URL "%s",
2509 			token->string);
2510 		os_free(auth->e_mud_url);
2511 		auth->e_mud_url = os_strdup(token->string);
2512 	}
2513 
2514 	token = json_get_member(root, "bandSupport");
2515 	auth->band_list_size = 0;
2516 	if (token && token->type == JSON_ARRAY) {
2517 		int *opclass = NULL;
2518 		char txt[200], *pos, *end;
2519 		int i, res;
2520 
2521 		memset(auth->band_list, 0, sizeof(auth->band_list));
2522 		wpa_printf(MSG_DEBUG, "DPP: bandSupport");
2523 		token = token->child;
2524 		while (token) {
2525 			if (token->type != JSON_NUMBER) {
2526 				wpa_printf(MSG_DEBUG,
2527 					   "DPP: Invalid bandSupport array member type");
2528 			} else {
2529 				if (auth->band_list_size < DPP_MAX_CHANNELS) {
2530 					auth->band_list[auth->band_list_size++] = token->number;
2531 				}
2532 				wpa_printf(MSG_DEBUG,
2533 					   "DPP: Supported global operating class: %d",
2534 					   token->number);
2535 				int_array_add_unique(&opclass, token->number);
2536 			}
2537 			token = token->sibling;
2538 		}
2539 
2540 		txt[0] = '\0';
2541 		pos = txt;
2542 		end = txt + sizeof(txt);
2543 		for (i = 0; opclass && opclass[i]; i++) {
2544 			res = os_snprintf(pos, end - pos, "%s%d",
2545 					  pos == txt ? "" : ",", opclass[i]);
2546 			if (os_snprintf_error(end - pos, res)) {
2547 				*pos = '\0';
2548 				break;
2549 			}
2550 			pos += res;
2551 		}
2552 		os_free(auth->e_band_support);
2553 		auth->e_band_support = opclass;
2554 		wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_BAND_SUPPORT "%s",
2555 			txt);
2556 	}
2557 
2558 #ifdef CONFIG_DPP2
2559 	cert_req = json_get_member_base64(root, "pkcs10");
2560 	if (cert_req) {
2561 		char *txt;
2562 		int id;
2563 
2564 		wpa_hexdump_buf(MSG_DEBUG, "DPP: CertificateRequest", cert_req);
2565 		if (dpp_validate_csr(auth, cert_req) < 0) {
2566 			wpa_printf(MSG_DEBUG, "DPP: CSR is not valid");
2567 			auth->force_conf_resp_status = DPP_STATUS_CSR_BAD;
2568 			goto cont;
2569 		}
2570 
2571 		id = dpp_get_peer_bi_id(auth);
2572 		if (id < 0)
2573 			goto fail;
2574 
2575 		wpa_printf(MSG_DEBUG, "DPP: CSR is valid - forward to CA/RA");
2576 		txt = base64_encode_no_lf(wpabuf_head(cert_req),
2577 					  wpabuf_len(cert_req), NULL);
2578 		if (!txt)
2579 			goto fail;
2580 
2581 		wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_CSR "peer=%d csr=%s",
2582 			id, txt);
2583 		os_free(txt);
2584 		auth->waiting_csr = false;
2585 		auth->waiting_cert = true;
2586 		goto fail;
2587 	}
2588 cont:
2589 #endif /* CONFIG_DPP2 */
2590 
2591 #ifdef CONFIG_DPP3
2592 	token = json_get_member(root, "capabilities");
2593 	if (token && token->type == JSON_NUMBER) {
2594 		wpa_printf(MSG_DEBUG, "DPP: capabilities = 0x%x",
2595 			   token->number);
2596 		wpa_msg(auth->msg_ctx, MSG_INFO,
2597 			DPP_EVENT_ENROLLEE_CAPABILITY "%d",
2598 			token->number);
2599 		auth->enrollee_capabilities = token->number;
2600 	}
2601 #endif /* CONFIG_DPP3 */
2602 
2603 	resp = dpp_build_conf_resp(auth, e_nonce, e_nonce_len, netrole,
2604 				   cert_req);
2605 
2606 fail:
2607 	wpabuf_free(cert_req);
2608 	json_free(root);
2609 	os_free(unwrapped);
2610 	return resp;
2611 }
2612 
2613 
dpp_parse_cred_legacy(struct dpp_config_obj * conf,struct json_token * cred)2614 static int dpp_parse_cred_legacy(struct dpp_config_obj *conf,
2615 				 struct json_token *cred)
2616 {
2617 	struct json_token *pass, *psk_hex;
2618 
2619 	wpa_printf(MSG_DEBUG, "DPP: Legacy akm=psk credential");
2620 
2621 	pass = json_get_member(cred, "pass");
2622 	psk_hex = json_get_member(cred, "psk_hex");
2623 
2624 	if (pass && pass->type == JSON_STRING) {
2625 		size_t len = os_strlen(pass->string);
2626 #ifdef CONFIG_DPP3
2627 		struct json_token *saepi = json_get_member(cred, "idpass");
2628 #endif /* CONFIG_DPP3 */
2629 
2630 		wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Legacy passphrase",
2631 				      pass->string, len);
2632 		if (dpp_akm_psk(conf->akm) && (len < 8 || len > 63)) {
2633 			wpa_printf(MSG_DEBUG,
2634 				   "DPP: Unexpected pass length %zu for a config object that includes PSK",
2635 				   len);
2636 			return -1;
2637 		}
2638 		os_strlcpy(conf->passphrase, pass->string,
2639 			   sizeof(conf->passphrase));
2640 #ifdef CONFIG_DPP3
2641 		if (saepi && saepi->type == JSON_STRING)
2642 			os_strlcpy(conf->password_id, saepi->string,
2643 				   sizeof(conf->password_id));
2644 #endif /* CONFIG_DPP3 */
2645 	} else if (psk_hex && psk_hex->type == JSON_STRING) {
2646 		if (dpp_akm_sae(conf->akm) && !dpp_akm_psk(conf->akm)) {
2647 			wpa_printf(MSG_DEBUG,
2648 				   "DPP: Unexpected psk_hex with akm=sae");
2649 			return -1;
2650 		}
2651 		if (os_strlen(psk_hex->string) != PMK_LEN * 2 ||
2652 		    hexstr2bin(psk_hex->string, conf->psk, PMK_LEN) < 0) {
2653 			wpa_printf(MSG_DEBUG, "DPP: Invalid psk_hex encoding");
2654 			return -1;
2655 		}
2656 		wpa_hexdump_key(MSG_DEBUG, "DPP: Legacy PSK",
2657 				conf->psk, PMK_LEN);
2658 		conf->psk_set = 1;
2659 	} else {
2660 		wpa_printf(MSG_DEBUG, "DPP: No pass or psk_hex strings found");
2661 		return -1;
2662 	}
2663 
2664 	if (dpp_akm_sae(conf->akm) && !conf->passphrase[0]) {
2665 		wpa_printf(MSG_DEBUG, "DPP: No pass for sae found");
2666 		return -1;
2667 	}
2668 
2669 	return 0;
2670 }
2671 
2672 
dpp_parse_jwk(struct json_token * jwk,const struct dpp_curve_params ** key_curve)2673 struct crypto_ec_key * dpp_parse_jwk(struct json_token *jwk,
2674 				     const struct dpp_curve_params **key_curve)
2675 {
2676 	struct json_token *token;
2677 	const struct dpp_curve_params *curve;
2678 	struct wpabuf *x = NULL, *y = NULL;
2679 	struct crypto_ec_key *key = NULL;
2680 
2681 	token = json_get_member(jwk, "kty");
2682 	if (!token || token->type != JSON_STRING) {
2683 		wpa_printf(MSG_DEBUG, "DPP: No kty in JWK");
2684 		goto fail;
2685 	}
2686 	if (os_strcmp(token->string, "EC") != 0) {
2687 		wpa_printf(MSG_DEBUG, "DPP: Unexpected JWK kty '%s'",
2688 			   token->string);
2689 		goto fail;
2690 	}
2691 
2692 	token = json_get_member(jwk, "crv");
2693 	if (!token || token->type != JSON_STRING) {
2694 		wpa_printf(MSG_DEBUG, "DPP: No crv in JWK");
2695 		goto fail;
2696 	}
2697 	curve = dpp_get_curve_jwk_crv(token->string);
2698 	if (!curve) {
2699 		wpa_printf(MSG_DEBUG, "DPP: Unsupported JWK crv '%s'",
2700 			   token->string);
2701 		goto fail;
2702 	}
2703 
2704 	x = json_get_member_base64url(jwk, "x");
2705 	if (!x) {
2706 		wpa_printf(MSG_DEBUG, "DPP: No x in JWK");
2707 		goto fail;
2708 	}
2709 	wpa_hexdump_buf(MSG_DEBUG, "DPP: JWK x", x);
2710 	if (wpabuf_len(x) != curve->prime_len) {
2711 		wpa_printf(MSG_DEBUG,
2712 			   "DPP: Unexpected JWK x length %u (expected %u for curve %s)",
2713 			   (unsigned int) wpabuf_len(x),
2714 			   (unsigned int) curve->prime_len, curve->name);
2715 		goto fail;
2716 	}
2717 
2718 	y = json_get_member_base64url(jwk, "y");
2719 	if (!y) {
2720 		wpa_printf(MSG_DEBUG, "DPP: No y in JWK");
2721 		goto fail;
2722 	}
2723 	wpa_hexdump_buf(MSG_DEBUG, "DPP: JWK y", y);
2724 	if (wpabuf_len(y) != curve->prime_len) {
2725 		wpa_printf(MSG_DEBUG,
2726 			   "DPP: Unexpected JWK y length %u (expected %u for curve %s)",
2727 			   (unsigned int) wpabuf_len(y),
2728 			   (unsigned int) curve->prime_len, curve->name);
2729 		goto fail;
2730 	}
2731 
2732 	key = crypto_ec_key_set_pub(curve->ike_group, wpabuf_head(x),
2733 				    wpabuf_head(y), wpabuf_len(x));
2734 	if (!key)
2735 		goto fail;
2736 
2737 	*key_curve = curve;
2738 
2739 fail:
2740 	wpabuf_free(x);
2741 	wpabuf_free(y);
2742 
2743 	return key;
2744 }
2745 
2746 
dpp_key_expired(const char * timestamp,os_time_t * expiry)2747 int dpp_key_expired(const char *timestamp, os_time_t *expiry)
2748 {
2749 	struct os_time now;
2750 	unsigned int year, month, day, hour, min, sec;
2751 	os_time_t utime;
2752 	const char *pos;
2753 
2754 	/* ISO 8601 date and time:
2755 	 * <date>T<time>
2756 	 * YYYY-MM-DDTHH:MM:SSZ
2757 	 * YYYY-MM-DDTHH:MM:SS+03:00
2758 	 */
2759 	if (os_strlen(timestamp) < 19) {
2760 		wpa_printf(MSG_DEBUG,
2761 			   "DPP: Too short timestamp - assume expired key");
2762 		return 1;
2763 	}
2764 	if (sscanf(timestamp, "%04u-%02u-%02uT%02u:%02u:%02u",
2765 		   &year, &month, &day, &hour, &min, &sec) != 6) {
2766 		wpa_printf(MSG_DEBUG,
2767 			   "DPP: Failed to parse expiration day - assume expired key");
2768 		return 1;
2769 	}
2770 
2771 	if (os_mktime(year, month, day, hour, min, sec, &utime) < 0) {
2772 		wpa_printf(MSG_DEBUG,
2773 			   "DPP: Invalid date/time information - assume expired key");
2774 		return 1;
2775 	}
2776 
2777 	pos = timestamp + 19;
2778 	if (*pos == 'Z' || *pos == '\0') {
2779 		/* In UTC - no need to adjust */
2780 	} else if (*pos == '-' || *pos == '+') {
2781 		int items;
2782 
2783 		/* Adjust local time to UTC */
2784 		items = sscanf(pos + 1, "%02u:%02u", &hour, &min);
2785 		if (items < 1) {
2786 			wpa_printf(MSG_DEBUG,
2787 				   "DPP: Invalid time zone designator (%s) - assume expired key",
2788 				   pos);
2789 			return 1;
2790 		}
2791 		if (*pos == '-')
2792 			utime += 3600 * hour;
2793 		if (*pos == '+')
2794 			utime -= 3600 * hour;
2795 		if (items > 1) {
2796 			if (*pos == '-')
2797 				utime += 60 * min;
2798 			if (*pos == '+')
2799 				utime -= 60 * min;
2800 		}
2801 	} else {
2802 		wpa_printf(MSG_DEBUG,
2803 			   "DPP: Invalid time zone designator (%s) - assume expired key",
2804 			   pos);
2805 		return 1;
2806 	}
2807 	if (expiry)
2808 		*expiry = utime;
2809 
2810 	if (os_get_time(&now) < 0) {
2811 		wpa_printf(MSG_DEBUG,
2812 			   "DPP: Cannot get current time - assume expired key");
2813 		return 1;
2814 	}
2815 
2816 	if (now.sec > utime) {
2817 		wpa_printf(MSG_DEBUG, "DPP: Key has expired (%lu < %lu)",
2818 			   utime, now.sec);
2819 		return 1;
2820 	}
2821 
2822 	return 0;
2823 }
2824 
2825 
dpp_parse_connector(struct dpp_authentication * auth,struct dpp_config_obj * conf,const unsigned char * payload,u16 payload_len)2826 static int dpp_parse_connector(struct dpp_authentication *auth,
2827 			       struct dpp_config_obj *conf,
2828 			       const unsigned char *payload,
2829 			       u16 payload_len)
2830 {
2831 	struct json_token *root, *groups, *netkey, *token;
2832 	int ret = -1;
2833 	struct crypto_ec_key *key = NULL;
2834 	const struct dpp_curve_params *curve;
2835 	unsigned int rules = 0;
2836 
2837 	root = json_parse((const char *) payload, payload_len);
2838 	if (!root) {
2839 		wpa_printf(MSG_DEBUG, "DPP: JSON parsing of connector failed");
2840 		goto fail;
2841 	}
2842 
2843 	groups = json_get_member(root, "groups");
2844 	if (!groups || groups->type != JSON_ARRAY) {
2845 		wpa_printf(MSG_DEBUG, "DPP: No groups array found");
2846 		goto skip_groups;
2847 	}
2848 	for (token = groups->child; token; token = token->sibling) {
2849 		struct json_token *id, *role;
2850 
2851 		id = json_get_member(token, "groupId");
2852 		if (!id || id->type != JSON_STRING) {
2853 			wpa_printf(MSG_DEBUG, "DPP: Missing groupId string");
2854 			goto fail;
2855 		}
2856 
2857 		role = json_get_member(token, "netRole");
2858 		if (!role || role->type != JSON_STRING) {
2859 			wpa_printf(MSG_DEBUG, "DPP: Missing netRole string");
2860 			goto fail;
2861 		}
2862 		wpa_printf(MSG_DEBUG,
2863 			   "DPP: connector group: groupId='%s' netRole='%s'",
2864 			   id->string, role->string);
2865 		rules++;
2866 	}
2867 skip_groups:
2868 
2869 	if (!rules) {
2870 		wpa_printf(MSG_DEBUG,
2871 			   "DPP: Connector includes no groups");
2872 		goto fail;
2873 	}
2874 
2875 	token = json_get_member(root, "expiry");
2876 	if (!token || token->type != JSON_STRING) {
2877 		wpa_printf(MSG_DEBUG,
2878 			   "DPP: No expiry string found - connector does not expire");
2879 	} else {
2880 		wpa_printf(MSG_DEBUG, "DPP: expiry = %s", token->string);
2881 		if (dpp_key_expired(token->string,
2882 				    &auth->net_access_key_expiry)) {
2883 			wpa_printf(MSG_DEBUG,
2884 				   "DPP: Connector (netAccessKey) has expired");
2885 			goto fail;
2886 		}
2887 	}
2888 
2889 	netkey = json_get_member(root, "netAccessKey");
2890 	if (!netkey || netkey->type != JSON_OBJECT) {
2891 		wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
2892 		goto fail;
2893 	}
2894 
2895 	key = dpp_parse_jwk(netkey, &curve);
2896 	if (!key)
2897 		goto fail;
2898 	dpp_debug_print_key("DPP: Received netAccessKey", key);
2899 
2900 	if (crypto_ec_key_cmp(key, auth->own_protocol_key)) {
2901 		wpa_printf(MSG_DEBUG,
2902 			   "DPP: netAccessKey in connector does not match own protocol key");
2903 #ifdef CONFIG_TESTING_OPTIONS
2904 		if (auth->ignore_netaccesskey_mismatch) {
2905 			wpa_printf(MSG_DEBUG,
2906 				   "DPP: TESTING - skip netAccessKey mismatch");
2907 		} else {
2908 			goto fail;
2909 		}
2910 #else /* CONFIG_TESTING_OPTIONS */
2911 		goto fail;
2912 #endif /* CONFIG_TESTING_OPTIONS */
2913 	}
2914 
2915 	ret = 0;
2916 fail:
2917 	crypto_ec_key_deinit(key);
2918 	json_free(root);
2919 	return ret;
2920 }
2921 
2922 
dpp_copy_csign(struct dpp_config_obj * conf,struct crypto_ec_key * csign)2923 static void dpp_copy_csign(struct dpp_config_obj *conf,
2924 			   struct crypto_ec_key *csign)
2925 {
2926 	struct wpabuf *c_sign_key;
2927 
2928 	c_sign_key = crypto_ec_key_get_subject_public_key(csign);
2929 	if (!c_sign_key)
2930 		return;
2931 
2932 	wpabuf_free(conf->c_sign_key);
2933 	conf->c_sign_key = c_sign_key;
2934 }
2935 
2936 
dpp_copy_ppkey(struct dpp_config_obj * conf,struct crypto_ec_key * ppkey)2937 static void dpp_copy_ppkey(struct dpp_config_obj *conf,
2938 			   struct crypto_ec_key *ppkey)
2939 {
2940 	struct wpabuf *pp_key;
2941 
2942 	pp_key = crypto_ec_key_get_subject_public_key(ppkey);
2943 	if (!pp_key)
2944 		return;
2945 
2946 	wpabuf_free(conf->pp_key);
2947 	conf->pp_key = pp_key;
2948 }
2949 
2950 
dpp_copy_netaccesskey(struct dpp_authentication * auth,struct dpp_config_obj * conf)2951 static void dpp_copy_netaccesskey(struct dpp_authentication *auth,
2952 				  struct dpp_config_obj *conf)
2953 {
2954 	struct wpabuf *net_access_key;
2955 	struct crypto_ec_key *own_key;
2956 
2957 	own_key = auth->own_protocol_key;
2958 #ifdef CONFIG_DPP2
2959 	if (auth->reconfig_connector_key == DPP_CONFIG_REUSEKEY &&
2960 	    auth->reconfig_old_protocol_key)
2961 		own_key = auth->reconfig_old_protocol_key;
2962 #endif /* CONFIG_DPP2 */
2963 
2964 	net_access_key = crypto_ec_key_get_ecprivate_key(own_key, true);
2965 	if (!net_access_key)
2966 		return;
2967 
2968 	wpabuf_free(auth->net_access_key);
2969 	auth->net_access_key = net_access_key;
2970 }
2971 
2972 
dpp_parse_cred_dpp(struct dpp_authentication * auth,struct dpp_config_obj * conf,struct json_token * cred)2973 static int dpp_parse_cred_dpp(struct dpp_authentication *auth,
2974 			      struct dpp_config_obj *conf,
2975 			      struct json_token *cred)
2976 {
2977 	struct dpp_signed_connector_info info;
2978 	struct json_token *token, *csign, *ppkey;
2979 	int ret = -1;
2980 	struct crypto_ec_key *csign_pub = NULL, *pp_pub = NULL;
2981 	const struct dpp_curve_params *key_curve = NULL, *pp_curve = NULL;
2982 	const char *signed_connector;
2983 
2984 	os_memset(&info, 0, sizeof(info));
2985 
2986 	if (dpp_akm_psk(conf->akm) || dpp_akm_sae(conf->akm)) {
2987 		wpa_printf(MSG_DEBUG,
2988 			   "DPP: Legacy credential included in Connector credential");
2989 		if (dpp_parse_cred_legacy(conf, cred) < 0)
2990 			return -1;
2991 	}
2992 
2993 	wpa_printf(MSG_DEBUG, "DPP: Connector credential");
2994 
2995 	csign = json_get_member(cred, "csign");
2996 	if (!csign || csign->type != JSON_OBJECT) {
2997 		wpa_printf(MSG_DEBUG, "DPP: No csign JWK in JSON");
2998 		goto fail;
2999 	}
3000 
3001 	csign_pub = dpp_parse_jwk(csign, &key_curve);
3002 	if (!csign_pub) {
3003 		wpa_printf(MSG_DEBUG, "DPP: Failed to parse csign JWK");
3004 		goto fail;
3005 	}
3006 	dpp_debug_print_key("DPP: Received C-sign-key", csign_pub);
3007 
3008 	ppkey = json_get_member(cred, "ppKey");
3009 	if (ppkey && ppkey->type == JSON_OBJECT) {
3010 		pp_pub = dpp_parse_jwk(ppkey, &pp_curve);
3011 		if (!pp_pub) {
3012 			wpa_printf(MSG_DEBUG, "DPP: Failed to parse ppKey JWK");
3013 			goto fail;
3014 		}
3015 		dpp_debug_print_key("DPP: Received ppKey", pp_pub);
3016 		if (key_curve != pp_curve) {
3017 			wpa_printf(MSG_DEBUG,
3018 				   "DPP: C-sign-key and ppKey do not use the same curve");
3019 			goto fail;
3020 		}
3021 	}
3022 
3023 	token = json_get_member(cred, "signedConnector");
3024 	if (!token || token->type != JSON_STRING) {
3025 		wpa_printf(MSG_DEBUG, "DPP: No signedConnector string found");
3026 		goto fail;
3027 	}
3028 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: signedConnector",
3029 			  token->string, os_strlen(token->string));
3030 	signed_connector = token->string;
3031 
3032 	if (os_strchr(signed_connector, '"') ||
3033 	    os_strchr(signed_connector, '\n')) {
3034 		wpa_printf(MSG_DEBUG,
3035 			   "DPP: Unexpected character in signedConnector");
3036 		goto fail;
3037 	}
3038 
3039 	if (dpp_process_signed_connector(&info, csign_pub,
3040 					 signed_connector) != DPP_STATUS_OK)
3041 		goto fail;
3042 
3043 	if (dpp_parse_connector(auth, conf,
3044 				info.payload, info.payload_len) < 0) {
3045 		wpa_printf(MSG_DEBUG, "DPP: Failed to parse connector");
3046 		goto fail;
3047 	}
3048 
3049 	os_free(conf->connector);
3050 	conf->connector = os_strdup(signed_connector);
3051 
3052 	dpp_copy_csign(conf, csign_pub);
3053 	if (pp_pub)
3054 		dpp_copy_ppkey(conf, pp_pub);
3055 	if (dpp_akm_dpp(conf->akm) || auth->peer_version >= 2)
3056 		dpp_copy_netaccesskey(auth, conf);
3057 
3058 	ret = 0;
3059 fail:
3060 	crypto_ec_key_deinit(csign_pub);
3061 	crypto_ec_key_deinit(pp_pub);
3062 	os_free(info.payload);
3063 	return ret;
3064 }
3065 
3066 
3067 #ifdef CONFIG_DPP2
dpp_parse_cred_dot1x(struct dpp_authentication * auth,struct dpp_config_obj * conf,struct json_token * cred)3068 static int dpp_parse_cred_dot1x(struct dpp_authentication *auth,
3069 				struct dpp_config_obj *conf,
3070 				struct json_token *cred)
3071 {
3072 	struct json_token *ent, *name;
3073 
3074 	ent = json_get_member(cred, "entCreds");
3075 	if (!ent || ent->type != JSON_OBJECT) {
3076 		dpp_auth_fail(auth, "No entCreds in JSON");
3077 		return -1;
3078 	}
3079 
3080 	conf->certbag = json_get_member_base64(ent, "certBag");
3081 	if (!conf->certbag) {
3082 		dpp_auth_fail(auth, "No certBag in JSON");
3083 		return -1;
3084 	}
3085 	wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Received certBag", conf->certbag);
3086 	conf->certs = crypto_pkcs7_get_certificates(conf->certbag);
3087 	if (!conf->certs) {
3088 		dpp_auth_fail(auth, "No certificates in certBag");
3089 		return -1;
3090 	}
3091 
3092 	conf->cacert = json_get_member_base64(ent, "caCert");
3093 	if (conf->cacert)
3094 		wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Received caCert",
3095 				conf->cacert);
3096 
3097 	name = json_get_member(ent, "trustedEapServerName");
3098 	if (name &&
3099 	    (name->type != JSON_STRING ||
3100 	     has_ctrl_char((const u8 *) name->string,
3101 			   os_strlen(name->string)))) {
3102 		dpp_auth_fail(auth,
3103 			      "Invalid trustedEapServerName type in JSON");
3104 		return -1;
3105 	}
3106 	if (name && name->string) {
3107 		wpa_printf(MSG_DEBUG, "DPP: Received trustedEapServerName: %s",
3108 			   name->string);
3109 		conf->server_name = os_strdup(name->string);
3110 		if (!conf->server_name)
3111 			return -1;
3112 	}
3113 
3114 	return 0;
3115 }
3116 #endif /* CONFIG_DPP2 */
3117 
3118 
dpp_akm_str(enum dpp_akm akm)3119 const char * dpp_akm_str(enum dpp_akm akm)
3120 {
3121 	switch (akm) {
3122 	case DPP_AKM_DPP:
3123 		return "dpp";
3124 	case DPP_AKM_PSK:
3125 		return "psk";
3126 	case DPP_AKM_SAE:
3127 		return "sae";
3128 	case DPP_AKM_PSK_SAE:
3129 		return "psk+sae";
3130 	case DPP_AKM_SAE_DPP:
3131 		return "dpp+sae";
3132 	case DPP_AKM_PSK_SAE_DPP:
3133 		return "dpp+psk+sae";
3134 	case DPP_AKM_DOT1X:
3135 		return "dot1x";
3136 	default:
3137 		return "??";
3138 	}
3139 }
3140 
3141 
dpp_akm_selector_str(enum dpp_akm akm)3142 const char * dpp_akm_selector_str(enum dpp_akm akm)
3143 {
3144 	switch (akm) {
3145 	case DPP_AKM_DPP:
3146 		return "506F9A02";
3147 	case DPP_AKM_PSK:
3148 		return "000FAC02+000FAC06";
3149 	case DPP_AKM_SAE:
3150 		return "000FAC08";
3151 	case DPP_AKM_PSK_SAE:
3152 		return "000FAC02+000FAC06+000FAC08";
3153 	case DPP_AKM_SAE_DPP:
3154 		return "506F9A02+000FAC08";
3155 	case DPP_AKM_PSK_SAE_DPP:
3156 		return "506F9A02+000FAC08+000FAC02+000FAC06";
3157 	case DPP_AKM_DOT1X:
3158 		return "000FAC01+000FAC05";
3159 	default:
3160 		return "??";
3161 	}
3162 }
3163 
3164 
dpp_akm_from_str(const char * akm)3165 static enum dpp_akm dpp_akm_from_str(const char *akm)
3166 {
3167 	const char *pos;
3168 	int dpp = 0, psk = 0, sae = 0, dot1x = 0;
3169 
3170 	if (os_strcmp(akm, "psk") == 0)
3171 		return DPP_AKM_PSK;
3172 	if (os_strcmp(akm, "sae") == 0)
3173 		return DPP_AKM_SAE;
3174 	if (os_strcmp(akm, "psk+sae") == 0)
3175 		return DPP_AKM_PSK_SAE;
3176 	if (os_strcmp(akm, "dpp") == 0)
3177 		return DPP_AKM_DPP;
3178 	if (os_strcmp(akm, "dpp+sae") == 0)
3179 		return DPP_AKM_SAE_DPP;
3180 	if (os_strcmp(akm, "dpp+psk+sae") == 0)
3181 		return DPP_AKM_PSK_SAE_DPP;
3182 	if (os_strcmp(akm, "dot1x") == 0)
3183 		return DPP_AKM_DOT1X;
3184 
3185 	pos = akm;
3186 	while (*pos) {
3187 		if (os_strlen(pos) < 8)
3188 			break;
3189 		if (os_strncasecmp(pos, "506F9A02", 8) == 0)
3190 			dpp = 1;
3191 		else if (os_strncasecmp(pos, "000FAC02", 8) == 0)
3192 			psk = 1;
3193 		else if (os_strncasecmp(pos, "000FAC06", 8) == 0)
3194 			psk = 1;
3195 		else if (os_strncasecmp(pos, "000FAC08", 8) == 0)
3196 			sae = 1;
3197 		else if (os_strncasecmp(pos, "000FAC01", 8) == 0)
3198 			dot1x = 1;
3199 		else if (os_strncasecmp(pos, "000FAC05", 8) == 0)
3200 			dot1x = 1;
3201 		pos += 8;
3202 		if (*pos != '+')
3203 			break;
3204 		pos++;
3205 	}
3206 
3207 	if (dpp && psk && sae)
3208 		return DPP_AKM_PSK_SAE_DPP;
3209 	if (dpp && sae)
3210 		return DPP_AKM_SAE_DPP;
3211 	if (dpp)
3212 		return DPP_AKM_DPP;
3213 	if (psk && sae)
3214 		return DPP_AKM_PSK_SAE;
3215 	if (sae)
3216 		return DPP_AKM_SAE;
3217 	if (psk)
3218 		return DPP_AKM_PSK;
3219 	if (dot1x)
3220 		return DPP_AKM_DOT1X;
3221 
3222 	return DPP_AKM_UNKNOWN;
3223 }
3224 
3225 
dpp_parse_conf_obj(struct dpp_authentication * auth,const u8 * conf_obj,u16 conf_obj_len)3226 static int dpp_parse_conf_obj(struct dpp_authentication *auth,
3227 			      const u8 *conf_obj, u16 conf_obj_len)
3228 {
3229 	int ret = -1;
3230 	struct json_token *root, *token, *discovery, *cred;
3231 	struct dpp_config_obj *conf;
3232 	struct wpabuf *ssid64 = NULL;
3233 	int legacy;
3234 
3235 	root = json_parse((const char *) conf_obj, conf_obj_len);
3236 	if (!root)
3237 		return -1;
3238 	if (root->type != JSON_OBJECT) {
3239 		dpp_auth_fail(auth, "JSON root is not an object");
3240 		goto fail;
3241 	}
3242 
3243 	token = json_get_member(root, "wi-fi_tech");
3244 	if (!token || token->type != JSON_STRING) {
3245 		dpp_auth_fail(auth, "No wi-fi_tech string value found");
3246 		goto fail;
3247 	}
3248 	if (os_strcmp(token->string, "infra") != 0) {
3249 		wpa_printf(MSG_DEBUG, "DPP: Unsupported wi-fi_tech value: '%s'",
3250 			   token->string);
3251 		dpp_auth_fail(auth, "Unsupported wi-fi_tech value");
3252 		goto fail;
3253 	}
3254 
3255 	discovery = json_get_member(root, "discovery");
3256 	if (!discovery || discovery->type != JSON_OBJECT) {
3257 		dpp_auth_fail(auth, "No discovery object in JSON");
3258 		goto fail;
3259 	}
3260 
3261 	ssid64 = json_get_member_base64url(discovery, "ssid64");
3262 	if (ssid64) {
3263 		wpa_hexdump_ascii(MSG_DEBUG, "DPP: discovery::ssid64",
3264 				  wpabuf_head(ssid64), wpabuf_len(ssid64));
3265 		if (wpabuf_len(ssid64) > SSID_MAX_LEN) {
3266 			dpp_auth_fail(auth, "Too long discovery::ssid64 value");
3267 			goto fail;
3268 		}
3269 	} else {
3270 		token = json_get_member(discovery, "ssid");
3271 		if (!token || token->type != JSON_STRING) {
3272 			dpp_auth_fail(auth,
3273 				      "No discovery::ssid string value found");
3274 			goto fail;
3275 		}
3276 		wpa_hexdump_ascii(MSG_DEBUG, "DPP: discovery::ssid",
3277 				  token->string, os_strlen(token->string));
3278 		if (os_strlen(token->string) > SSID_MAX_LEN) {
3279 			dpp_auth_fail(auth,
3280 				      "Too long discovery::ssid string value");
3281 			goto fail;
3282 		}
3283 	}
3284 
3285 	if (auth->num_conf_obj == DPP_MAX_CONF_OBJ) {
3286 		wpa_printf(MSG_DEBUG,
3287 			   "DPP: No room for this many Config Objects - ignore this one");
3288 		ret = 0;
3289 		goto fail;
3290 	}
3291 	conf = &auth->conf_obj[auth->num_conf_obj++];
3292 
3293 	if (ssid64) {
3294 		conf->ssid_len = wpabuf_len(ssid64);
3295 		os_memcpy(conf->ssid, wpabuf_head(ssid64), conf->ssid_len);
3296 	} else {
3297 		conf->ssid_len = os_strlen(token->string);
3298 		os_memcpy(conf->ssid, token->string, conf->ssid_len);
3299 	}
3300 
3301 	token = json_get_member(discovery, "ssid_charset");
3302 	if (token && token->type == JSON_NUMBER) {
3303 		conf->ssid_charset = token->number;
3304 		wpa_printf(MSG_DEBUG, "DPP: ssid_charset=%d",
3305 			   conf->ssid_charset);
3306 	}
3307 
3308 	cred = json_get_member(root, "cred");
3309 	if (!cred || cred->type != JSON_OBJECT) {
3310 		dpp_auth_fail(auth, "No cred object in JSON");
3311 		goto fail;
3312 	}
3313 
3314 	token = json_get_member(cred, "akm");
3315 	if (!token || token->type != JSON_STRING) {
3316 		dpp_auth_fail(auth, "No cred::akm string value found");
3317 		goto fail;
3318 	}
3319 	conf->akm = dpp_akm_from_str(token->string);
3320 
3321 	legacy = dpp_akm_legacy(conf->akm);
3322 	if (legacy && auth->peer_version >= 2) {
3323 		struct json_token *csign, *s_conn;
3324 
3325 		csign = json_get_member(cred, "csign");
3326 		s_conn = json_get_member(cred, "signedConnector");
3327 		if (csign && csign->type == JSON_OBJECT &&
3328 		    s_conn && s_conn->type == JSON_STRING)
3329 			legacy = 0;
3330 	}
3331 	if (legacy) {
3332 		if (dpp_parse_cred_legacy(conf, cred) < 0)
3333 			goto fail;
3334 	} else if (dpp_akm_dpp(conf->akm) ||
3335 		   (auth->peer_version >= 2 && dpp_akm_legacy(conf->akm))) {
3336 		if (dpp_parse_cred_dpp(auth, conf, cred) < 0)
3337 			goto fail;
3338 #ifdef CONFIG_DPP2
3339 	} else if (conf->akm == DPP_AKM_DOT1X) {
3340 		if (dpp_parse_cred_dot1x(auth, conf, cred) < 0 ||
3341 		    dpp_parse_cred_dpp(auth, conf, cred) < 0)
3342 			goto fail;
3343 #endif /* CONFIG_DPP2 */
3344 	} else {
3345 		wpa_printf(MSG_DEBUG, "DPP: Unsupported akm: %s",
3346 			   token->string);
3347 		dpp_auth_fail(auth, "Unsupported akm");
3348 		goto fail;
3349 	}
3350 
3351 	wpa_printf(MSG_DEBUG, "DPP: JSON parsing completed successfully");
3352 	ret = 0;
3353 fail:
3354 	wpabuf_free(ssid64);
3355 	json_free(root);
3356 	return ret;
3357 }
3358 
3359 
3360 #ifdef CONFIG_DPP2
dpp_get_csr_attrs(const u8 * attrs,size_t attrs_len,size_t * len)3361 static u8 * dpp_get_csr_attrs(const u8 *attrs, size_t attrs_len, size_t *len)
3362 {
3363 	const u8 *b64;
3364 	u16 b64_len;
3365 
3366 	b64 = dpp_get_attr(attrs, attrs_len, DPP_ATTR_CSR_ATTR_REQ, &b64_len);
3367 	if (!b64)
3368 		return NULL;
3369 	return base64_decode((const char *) b64, b64_len, len);
3370 }
3371 #endif /* CONFIG_DPP2 */
3372 
3373 
dpp_conf_resp_rx(struct dpp_authentication * auth,const struct wpabuf * resp)3374 int dpp_conf_resp_rx(struct dpp_authentication *auth,
3375 		     const struct wpabuf *resp)
3376 {
3377 	const u8 *wrapped_data, *e_nonce, *status, *conf_obj;
3378 	u16 wrapped_data_len, e_nonce_len, status_len, conf_obj_len;
3379 	const u8 *env_data;
3380 	u16 env_data_len;
3381 	const u8 *addr[1];
3382 	size_t len[1];
3383 	u8 *unwrapped = NULL;
3384 	size_t unwrapped_len = 0;
3385 	int ret = -1;
3386 
3387 	auth->conf_resp_status = 255;
3388 
3389 	if (dpp_check_attrs(wpabuf_head(resp), wpabuf_len(resp)) < 0) {
3390 		dpp_auth_fail(auth, "Invalid attribute in config response");
3391 		return -1;
3392 	}
3393 
3394 	wrapped_data = dpp_get_attr(wpabuf_head(resp), wpabuf_len(resp),
3395 				    DPP_ATTR_WRAPPED_DATA,
3396 				    &wrapped_data_len);
3397 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
3398 		dpp_auth_fail(auth,
3399 			      "Missing or invalid required Wrapped Data attribute");
3400 		return -1;
3401 	}
3402 
3403 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
3404 		    wrapped_data, wrapped_data_len);
3405 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
3406 	unwrapped = os_malloc(unwrapped_len);
3407 	if (!unwrapped)
3408 		return -1;
3409 
3410 	addr[0] = wpabuf_head(resp);
3411 	len[0] = wrapped_data - 4 - (const u8 *) wpabuf_head(resp);
3412 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]);
3413 
3414 	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
3415 			    wrapped_data, wrapped_data_len,
3416 			    1, addr, len, unwrapped) < 0) {
3417 		dpp_auth_fail(auth, "AES-SIV decryption failed");
3418 		goto fail;
3419 	}
3420 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
3421 		    unwrapped, unwrapped_len);
3422 
3423 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
3424 		dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
3425 		goto fail;
3426 	}
3427 
3428 	e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
3429 			       DPP_ATTR_ENROLLEE_NONCE,
3430 			       &e_nonce_len);
3431 	if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
3432 		dpp_auth_fail(auth,
3433 			      "Missing or invalid Enrollee Nonce attribute");
3434 		goto fail;
3435 	}
3436 	wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
3437 	if (os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) {
3438 		dpp_auth_fail(auth, "Enrollee Nonce mismatch");
3439 		goto fail;
3440 	}
3441 
3442 	status = dpp_get_attr(wpabuf_head(resp), wpabuf_len(resp),
3443 			      DPP_ATTR_STATUS, &status_len);
3444 	if (!status || status_len < 1) {
3445 		dpp_auth_fail(auth,
3446 			      "Missing or invalid required DPP Status attribute");
3447 		goto fail;
3448 	}
3449 	auth->conf_resp_status = status[0];
3450 	wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
3451 #ifdef CONFIG_DPP2
3452 	if (status[0] == DPP_STATUS_CSR_NEEDED) {
3453 		u8 *csrattrs;
3454 		size_t csrattrs_len;
3455 
3456 		wpa_printf(MSG_DEBUG, "DPP: Configurator requested CSR");
3457 
3458 		csrattrs = dpp_get_csr_attrs(unwrapped, unwrapped_len,
3459 					     &csrattrs_len);
3460 		if (!csrattrs) {
3461 			dpp_auth_fail(auth,
3462 				      "Missing or invalid CSR Attributes Request attribute");
3463 			goto fail;
3464 		}
3465 		wpa_hexdump(MSG_DEBUG, "DPP: CsrAttrs", csrattrs, csrattrs_len);
3466 		os_free(auth->csrattrs);
3467 		auth->csrattrs = csrattrs;
3468 		auth->csrattrs_len = csrattrs_len;
3469 		ret = -2;
3470 		goto fail;
3471 	}
3472 #endif /* CONFIG_DPP2 */
3473 #ifdef CONFIG_DPP3
3474 	if (status[0] == DPP_STATUS_NEW_KEY_NEEDED) {
3475 		const u8 *fcgroup, *r_proto;
3476 		u16 fcgroup_len, r_proto_len;
3477 		u16 group;
3478 		const struct dpp_curve_params *curve;
3479 		struct crypto_ec_key *new_pe;
3480 		struct crypto_ec_key *pc;
3481 
3482 		fcgroup = dpp_get_attr(unwrapped, unwrapped_len,
3483 				       DPP_ATTR_FINITE_CYCLIC_GROUP,
3484 				       &fcgroup_len);
3485 		if (!fcgroup || fcgroup_len != 2) {
3486 			dpp_auth_fail(auth,
3487 				      "Missing or invalid required Finite Cyclic Group attribute");
3488 			goto fail;
3489 		}
3490 		group = WPA_GET_LE16(fcgroup);
3491 
3492 		wpa_printf(MSG_DEBUG,
3493 			   "DPP: Configurator requested a new protocol key from group %u",
3494 			   group);
3495 		curve = dpp_get_curve_ike_group(group);
3496 		if (!curve) {
3497 			dpp_auth_fail(auth,
3498 				      "Unsupported group for new protocol key");
3499 			goto fail;
3500 		}
3501 
3502 		new_pe = dpp_gen_keypair(curve);
3503 		if (!new_pe) {
3504 			dpp_auth_fail(auth,
3505 				      "Failed to generate a new protocol key");
3506 			goto fail;
3507 		}
3508 
3509 		crypto_ec_key_deinit(auth->own_protocol_key);
3510 		auth->own_protocol_key = new_pe;
3511 		auth->new_curve = curve;
3512 
3513 		r_proto = dpp_get_attr(unwrapped, unwrapped_len,
3514 				       DPP_ATTR_R_PROTOCOL_KEY,
3515 				       &r_proto_len);
3516 		if (!r_proto) {
3517 			dpp_auth_fail(auth,
3518 				      "Missing required Responder Protocol Key attribute (Pc)");
3519 			goto fail;
3520 		}
3521 		wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Protocol Key (new Pc)",
3522 			    r_proto, r_proto_len);
3523 
3524 		pc = dpp_set_pubkey_point(new_pe, r_proto, r_proto_len);
3525 		if (!pc) {
3526 			dpp_auth_fail(auth, "Invalid Responder Protocol Key (Pc)");
3527 			goto fail;
3528 		}
3529 		dpp_debug_print_key("New Peer Protocol Key (Pc)", pc);
3530 
3531 		crypto_ec_key_deinit(auth->peer_protocol_key);
3532 		auth->peer_protocol_key = pc;
3533 
3534 		auth->waiting_new_key = true;
3535 		ret = -3;
3536 		goto fail;
3537 	}
3538 #endif /* CONFIG_DPP3 */
3539 	if (status[0] != DPP_STATUS_OK) {
3540 		dpp_auth_fail(auth, "Configurator rejected configuration");
3541 		goto fail;
3542 	}
3543 
3544 	env_data = dpp_get_attr(unwrapped, unwrapped_len,
3545 				DPP_ATTR_ENVELOPED_DATA, &env_data_len);
3546 #ifdef CONFIG_DPP2
3547 	if (env_data &&
3548 	    dpp_conf_resp_env_data(auth, env_data, env_data_len) < 0)
3549 		goto fail;
3550 #endif /* CONFIG_DPP2 */
3551 
3552 	conf_obj = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_CONFIG_OBJ,
3553 				&conf_obj_len);
3554 	if (!conf_obj && !env_data) {
3555 		dpp_auth_fail(auth,
3556 			      "Missing required Configuration Object attribute");
3557 		goto fail;
3558 	}
3559 	while (conf_obj) {
3560 		wpa_hexdump_ascii(MSG_DEBUG, "DPP: configurationObject JSON",
3561 				  conf_obj, conf_obj_len);
3562 		if (dpp_parse_conf_obj(auth, conf_obj, conf_obj_len) < 0)
3563 			goto fail;
3564 		conf_obj = dpp_get_attr_next(conf_obj, unwrapped, unwrapped_len,
3565 					     DPP_ATTR_CONFIG_OBJ,
3566 					     &conf_obj_len);
3567 	}
3568 
3569 #ifdef CONFIG_DPP2
3570 	status = dpp_get_attr(unwrapped, unwrapped_len,
3571 			      DPP_ATTR_SEND_CONN_STATUS, &status_len);
3572 	if (status) {
3573 		wpa_printf(MSG_DEBUG,
3574 			   "DPP: Configurator requested connection status result");
3575 		auth->conn_status_requested = 1;
3576 	}
3577 #endif /* CONFIG_DPP2 */
3578 
3579 	ret = 0;
3580 
3581 fail:
3582 	os_free(unwrapped);
3583 	return ret;
3584 }
3585 
3586 
3587 #ifdef CONFIG_DPP2
3588 
dpp_conf_result_rx(struct dpp_authentication * auth,const u8 * hdr,const u8 * attr_start,size_t attr_len)3589 enum dpp_status_error dpp_conf_result_rx(struct dpp_authentication *auth,
3590 					 const u8 *hdr,
3591 					 const u8 *attr_start, size_t attr_len)
3592 {
3593 	const u8 *wrapped_data, *status, *e_nonce;
3594 	u16 wrapped_data_len, status_len, e_nonce_len;
3595 	const u8 *addr[2];
3596 	size_t len[2];
3597 	u8 *unwrapped = NULL;
3598 	size_t unwrapped_len = 0;
3599 	enum dpp_status_error ret = 256;
3600 
3601 	wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
3602 				    &wrapped_data_len);
3603 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
3604 		dpp_auth_fail(auth,
3605 			      "Missing or invalid required Wrapped Data attribute");
3606 		goto fail;
3607 	}
3608 	wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data",
3609 		    wrapped_data, wrapped_data_len);
3610 
3611 	attr_len = wrapped_data - 4 - attr_start;
3612 
3613 	addr[0] = hdr;
3614 	len[0] = DPP_HDR_LEN;
3615 	addr[1] = attr_start;
3616 	len[1] = attr_len;
3617 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
3618 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
3619 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
3620 		    wrapped_data, wrapped_data_len);
3621 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
3622 	unwrapped = os_malloc(unwrapped_len);
3623 	if (!unwrapped)
3624 		goto fail;
3625 	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
3626 			    wrapped_data, wrapped_data_len,
3627 			    2, addr, len, unwrapped) < 0) {
3628 		dpp_auth_fail(auth, "AES-SIV decryption failed");
3629 		goto fail;
3630 	}
3631 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
3632 		    unwrapped, unwrapped_len);
3633 
3634 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
3635 		dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
3636 		goto fail;
3637 	}
3638 
3639 	e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
3640 			       DPP_ATTR_ENROLLEE_NONCE,
3641 			       &e_nonce_len);
3642 	if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
3643 		dpp_auth_fail(auth,
3644 			      "Missing or invalid Enrollee Nonce attribute");
3645 		goto fail;
3646 	}
3647 	wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
3648 	if (os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) {
3649 		dpp_auth_fail(auth, "Enrollee Nonce mismatch");
3650 		wpa_hexdump(MSG_DEBUG, "DPP: Expected Enrollee Nonce",
3651 			    auth->e_nonce, e_nonce_len);
3652 		goto fail;
3653 	}
3654 
3655 	status = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_STATUS,
3656 			      &status_len);
3657 	if (!status || status_len < 1) {
3658 		dpp_auth_fail(auth,
3659 			      "Missing or invalid required DPP Status attribute");
3660 		goto fail;
3661 	}
3662 	wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
3663 	ret = status[0];
3664 
3665 fail:
3666 	bin_clear_free(unwrapped, unwrapped_len);
3667 	return ret;
3668 }
3669 
3670 
dpp_build_conf_result(struct dpp_authentication * auth,enum dpp_status_error status)3671 struct wpabuf * dpp_build_conf_result(struct dpp_authentication *auth,
3672 				      enum dpp_status_error status)
3673 {
3674 	struct wpabuf *msg, *clear;
3675 	size_t nonce_len, clear_len, attr_len;
3676 	const u8 *addr[2];
3677 	size_t len[2];
3678 	u8 *wrapped;
3679 
3680 	nonce_len = auth->curve->nonce_len;
3681 	clear_len = 5 + 4 + nonce_len;
3682 	attr_len = 4 + clear_len + AES_BLOCK_SIZE;
3683 	clear = wpabuf_alloc(clear_len);
3684 	msg = dpp_alloc_msg(DPP_PA_CONFIGURATION_RESULT, attr_len);
3685 	if (!clear || !msg)
3686 		goto fail;
3687 
3688 	/* DPP Status */
3689 	dpp_build_attr_status(clear, status);
3690 
3691 	/* E-nonce */
3692 	wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
3693 	wpabuf_put_le16(clear, nonce_len);
3694 	wpabuf_put_data(clear, auth->e_nonce, nonce_len);
3695 
3696 	/* OUI, OUI type, Crypto Suite, DPP frame type */
3697 	addr[0] = wpabuf_head_u8(msg) + 2;
3698 	len[0] = 3 + 1 + 1 + 1;
3699 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
3700 
3701 	/* Attributes before Wrapped Data (none) */
3702 	addr[1] = wpabuf_put(msg, 0);
3703 	len[1] = 0;
3704 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
3705 
3706 	/* Wrapped Data */
3707 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
3708 	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
3709 	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
3710 
3711 	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
3712 	if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
3713 			    wpabuf_head(clear), wpabuf_len(clear),
3714 			    2, addr, len, wrapped) < 0)
3715 		goto fail;
3716 
3717 	wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Result attributes", msg);
3718 	wpabuf_free(clear);
3719 	return msg;
3720 fail:
3721 	wpabuf_free(clear);
3722 	wpabuf_free(msg);
3723 	return NULL;
3724 }
3725 
3726 
valid_channel_list(const char * val)3727 static int valid_channel_list(const char *val)
3728 {
3729 	while (*val) {
3730 		if (!((*val >= '0' && *val <= '9') ||
3731 		      *val == '/' || *val == ','))
3732 			return 0;
3733 		val++;
3734 	}
3735 
3736 	return 1;
3737 }
3738 
3739 
dpp_conn_status_result_rx(struct dpp_authentication * auth,const u8 * hdr,const u8 * attr_start,size_t attr_len,u8 * ssid,size_t * ssid_len,char ** channel_list)3740 enum dpp_status_error dpp_conn_status_result_rx(struct dpp_authentication *auth,
3741 						const u8 *hdr,
3742 						const u8 *attr_start,
3743 						size_t attr_len,
3744 						u8 *ssid, size_t *ssid_len,
3745 						char **channel_list)
3746 {
3747 	const u8 *wrapped_data, *status, *e_nonce;
3748 	u16 wrapped_data_len, status_len, e_nonce_len;
3749 	const u8 *addr[2];
3750 	size_t len[2];
3751 	u8 *unwrapped = NULL;
3752 	size_t unwrapped_len = 0;
3753 	enum dpp_status_error ret = 256;
3754 	struct json_token *root = NULL, *token;
3755 	struct wpabuf *ssid64;
3756 
3757 	*ssid_len = 0;
3758 	*channel_list = NULL;
3759 
3760 	wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
3761 				    &wrapped_data_len);
3762 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
3763 		dpp_auth_fail(auth,
3764 			      "Missing or invalid required Wrapped Data attribute");
3765 		goto fail;
3766 	}
3767 	wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data",
3768 		    wrapped_data, wrapped_data_len);
3769 
3770 	attr_len = wrapped_data - 4 - attr_start;
3771 
3772 	addr[0] = hdr;
3773 	len[0] = DPP_HDR_LEN;
3774 	addr[1] = attr_start;
3775 	len[1] = attr_len;
3776 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
3777 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
3778 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
3779 		    wrapped_data, wrapped_data_len);
3780 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
3781 	unwrapped = os_malloc(unwrapped_len);
3782 	if (!unwrapped)
3783 		goto fail;
3784 	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
3785 			    wrapped_data, wrapped_data_len,
3786 			    2, addr, len, unwrapped) < 0) {
3787 		dpp_auth_fail(auth, "AES-SIV decryption failed");
3788 		goto fail;
3789 	}
3790 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
3791 		    unwrapped, unwrapped_len);
3792 
3793 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
3794 		dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
3795 		goto fail;
3796 	}
3797 
3798 	e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
3799 			       DPP_ATTR_ENROLLEE_NONCE,
3800 			       &e_nonce_len);
3801 	if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
3802 		dpp_auth_fail(auth,
3803 			      "Missing or invalid Enrollee Nonce attribute");
3804 		goto fail;
3805 	}
3806 	wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
3807 	if (os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) {
3808 		dpp_auth_fail(auth, "Enrollee Nonce mismatch");
3809 		wpa_hexdump(MSG_DEBUG, "DPP: Expected Enrollee Nonce",
3810 			    auth->e_nonce, e_nonce_len);
3811 		goto fail;
3812 	}
3813 
3814 	status = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_CONN_STATUS,
3815 			      &status_len);
3816 	if (!status) {
3817 		dpp_auth_fail(auth,
3818 			      "Missing required DPP Connection Status attribute");
3819 		goto fail;
3820 	}
3821 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: connStatus JSON",
3822 			  status, status_len);
3823 
3824 	root = json_parse((const char *) status, status_len);
3825 	if (!root) {
3826 		dpp_auth_fail(auth, "Could not parse connStatus");
3827 		goto fail;
3828 	}
3829 
3830 	ssid64 = json_get_member_base64url(root, "ssid64");
3831 	if (ssid64 && wpabuf_len(ssid64) <= SSID_MAX_LEN) {
3832 		*ssid_len = wpabuf_len(ssid64);
3833 		os_memcpy(ssid, wpabuf_head(ssid64), *ssid_len);
3834 	}
3835 	wpabuf_free(ssid64);
3836 
3837 	token = json_get_member(root, "channelList");
3838 	if (token && token->type == JSON_STRING &&
3839 	    valid_channel_list(token->string))
3840 		*channel_list = os_strdup(token->string);
3841 
3842 	token = json_get_member(root, "result");
3843 	if (!token || token->type != JSON_NUMBER) {
3844 		dpp_auth_fail(auth, "No connStatus - result");
3845 		goto fail;
3846 	}
3847 	wpa_printf(MSG_DEBUG, "DPP: result %d", token->number);
3848 	ret = token->number;
3849 
3850 fail:
3851 	json_free(root);
3852 	bin_clear_free(unwrapped, unwrapped_len);
3853 	return ret;
3854 }
3855 
3856 
dpp_build_conn_status(enum dpp_status_error result,const u8 * ssid,size_t ssid_len,const char * channel_list)3857 struct wpabuf * dpp_build_conn_status(enum dpp_status_error result,
3858 				      const u8 *ssid, size_t ssid_len,
3859 				      const char *channel_list)
3860 {
3861 	struct wpabuf *json;
3862 
3863 	json = wpabuf_alloc(1000);
3864 	if (!json)
3865 		return NULL;
3866 	json_start_object(json, NULL);
3867 	json_add_int(json, "result", result);
3868 	if (ssid) {
3869 		json_value_sep(json);
3870 		if (json_add_base64url(json, "ssid64", ssid, ssid_len) < 0) {
3871 			wpabuf_free(json);
3872 			return NULL;
3873 		}
3874 	}
3875 	if (channel_list) {
3876 		json_value_sep(json);
3877 		json_add_string(json, "channelList", channel_list);
3878 	}
3879 	json_end_object(json);
3880 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: connStatus JSON",
3881 			  wpabuf_head(json), wpabuf_len(json));
3882 
3883 	return json;
3884 }
3885 
3886 
dpp_build_conn_status_result(struct dpp_authentication * auth,enum dpp_status_error result,const u8 * ssid,size_t ssid_len,const char * channel_list)3887 struct wpabuf * dpp_build_conn_status_result(struct dpp_authentication *auth,
3888 					     enum dpp_status_error result,
3889 					     const u8 *ssid, size_t ssid_len,
3890 					     const char *channel_list)
3891 {
3892 	struct wpabuf *msg = NULL, *clear = NULL, *json;
3893 	size_t nonce_len, clear_len, attr_len;
3894 	const u8 *addr[2];
3895 	size_t len[2];
3896 	u8 *wrapped;
3897 
3898 	json = dpp_build_conn_status(result, ssid, ssid_len, channel_list);
3899 	if (!json)
3900 		return NULL;
3901 
3902 	nonce_len = auth->curve->nonce_len;
3903 	clear_len = 5 + 4 + nonce_len + 4 + wpabuf_len(json);
3904 	attr_len = 4 + clear_len + AES_BLOCK_SIZE;
3905 	clear = wpabuf_alloc(clear_len);
3906 	msg = dpp_alloc_msg(DPP_PA_CONNECTION_STATUS_RESULT, attr_len);
3907 	if (!clear || !msg)
3908 		goto fail;
3909 
3910 	/* E-nonce */
3911 	wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
3912 	wpabuf_put_le16(clear, nonce_len);
3913 	wpabuf_put_data(clear, auth->e_nonce, nonce_len);
3914 
3915 	/* DPP Connection Status */
3916 	wpabuf_put_le16(clear, DPP_ATTR_CONN_STATUS);
3917 	wpabuf_put_le16(clear, wpabuf_len(json));
3918 	wpabuf_put_buf(clear, json);
3919 
3920 	/* OUI, OUI type, Crypto Suite, DPP frame type */
3921 	addr[0] = wpabuf_head_u8(msg) + 2;
3922 	len[0] = 3 + 1 + 1 + 1;
3923 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
3924 
3925 	/* Attributes before Wrapped Data (none) */
3926 	addr[1] = wpabuf_put(msg, 0);
3927 	len[1] = 0;
3928 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
3929 
3930 	/* Wrapped Data */
3931 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
3932 	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
3933 	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
3934 
3935 	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
3936 	if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
3937 			    wpabuf_head(clear), wpabuf_len(clear),
3938 			    2, addr, len, wrapped) < 0)
3939 		goto fail;
3940 
3941 	wpa_hexdump_buf(MSG_DEBUG, "DPP: Connection Status Result attributes",
3942 			msg);
3943 	wpabuf_free(json);
3944 	wpabuf_free(clear);
3945 	return msg;
3946 fail:
3947 	wpabuf_free(json);
3948 	wpabuf_free(clear);
3949 	wpabuf_free(msg);
3950 	return NULL;
3951 }
3952 
3953 #endif /* CONFIG_DPP2 */
3954 
3955 
dpp_configurator_free(struct dpp_configurator * conf)3956 void dpp_configurator_free(struct dpp_configurator *conf)
3957 {
3958 	if (!conf)
3959 		return;
3960 	crypto_ec_key_deinit(conf->csign);
3961 	os_free(conf->kid);
3962 	os_free(conf->connector);
3963 	crypto_ec_key_deinit(conf->connector_key);
3964 	crypto_ec_key_deinit(conf->pp_key);
3965 	os_free(conf);
3966 }
3967 
3968 
dpp_configurator_get_key(const struct dpp_configurator * conf,char * buf,size_t buflen)3969 int dpp_configurator_get_key(const struct dpp_configurator *conf, char *buf,
3970 			     size_t buflen)
3971 {
3972 	struct wpabuf *key;
3973 	int ret = -1;
3974 
3975 	if (!conf->csign)
3976 		return -1;
3977 
3978 	key = crypto_ec_key_get_ecprivate_key(conf->csign, true);
3979 	if (!key)
3980 		return -1;
3981 
3982 	ret = wpa_snprintf_hex(buf, buflen, wpabuf_head(key), wpabuf_len(key));
3983 
3984 	wpabuf_clear_free(key);
3985 	return ret;
3986 }
3987 
3988 
dpp_configurator_gen_kid(struct dpp_configurator * conf)3989 static int dpp_configurator_gen_kid(struct dpp_configurator *conf)
3990 {
3991 	struct wpabuf *csign_pub = NULL;
3992 	const u8 *addr[1];
3993 	size_t len[1];
3994 	int res;
3995 
3996 	csign_pub = crypto_ec_key_get_pubkey_point(conf->csign, 1);
3997 	if (!csign_pub) {
3998 		wpa_printf(MSG_INFO, "DPP: Failed to extract C-sign-key");
3999 		return -1;
4000 	}
4001 
4002 	/* kid = SHA256(ANSI X9.63 uncompressed C-sign-key) */
4003 	addr[0] = wpabuf_head(csign_pub);
4004 	len[0] = wpabuf_len(csign_pub);
4005 	res = sha256_vector(1, addr, len, conf->kid_hash);
4006 	wpabuf_free(csign_pub);
4007 	if (res < 0) {
4008 		wpa_printf(MSG_DEBUG,
4009 			   "DPP: Failed to derive kid for C-sign-key");
4010 		return -1;
4011 	}
4012 
4013 	conf->kid = base64_url_encode(conf->kid_hash, sizeof(conf->kid_hash),
4014 				      NULL);
4015 	return conf->kid ? 0 : -1;
4016 }
4017 
4018 
4019 static struct dpp_configurator *
dpp_keygen_configurator(const char * curve,const u8 * privkey,size_t privkey_len,const u8 * pp_key,size_t pp_key_len)4020 dpp_keygen_configurator(const char *curve, const u8 *privkey,
4021 			size_t privkey_len, const u8 *pp_key, size_t pp_key_len)
4022 {
4023 	struct dpp_configurator *conf;
4024 
4025 	conf = os_zalloc(sizeof(*conf));
4026 	if (!conf)
4027 		return NULL;
4028 
4029 	conf->curve = dpp_get_curve_name(curve);
4030 	if (!conf->curve) {
4031 		wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", curve);
4032 		os_free(conf);
4033 		return NULL;
4034 	}
4035 
4036 	if (privkey)
4037 		conf->csign = dpp_set_keypair(&conf->curve, privkey,
4038 					      privkey_len);
4039 	else
4040 		conf->csign = dpp_gen_keypair(conf->curve);
4041 	if (pp_key)
4042 		conf->pp_key = dpp_set_keypair(&conf->curve, pp_key,
4043 					       pp_key_len);
4044 	else
4045 		conf->pp_key = dpp_gen_keypair(conf->curve);
4046 	if (!conf->csign || !conf->pp_key)
4047 		goto fail;
4048 	conf->own = 1;
4049 
4050 	if (dpp_configurator_gen_kid(conf) < 0)
4051 		goto fail;
4052 	return conf;
4053 fail:
4054 	dpp_configurator_free(conf);
4055 	return NULL;
4056 }
4057 
4058 
dpp_configurator_own_config(struct dpp_authentication * auth,const char * curve,int ap)4059 int dpp_configurator_own_config(struct dpp_authentication *auth,
4060 				const char *curve, int ap)
4061 {
4062 	struct wpabuf *conf_obj;
4063 	int ret = -1;
4064 
4065 	if (!auth->conf) {
4066 		wpa_printf(MSG_DEBUG, "DPP: No configurator specified");
4067 		return -1;
4068 	}
4069 
4070 	auth->curve = dpp_get_curve_name(curve);
4071 	if (!auth->curve) {
4072 		wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", curve);
4073 		return -1;
4074 	}
4075 
4076 	wpa_printf(MSG_DEBUG,
4077 		   "DPP: Building own configuration/connector with curve %s",
4078 		   auth->curve->name);
4079 
4080 	auth->own_protocol_key = dpp_gen_keypair(auth->curve);
4081 	if (!auth->own_protocol_key)
4082 		return -1;
4083 	dpp_copy_netaccesskey(auth, &auth->conf_obj[0]);
4084 	auth->peer_protocol_key = auth->own_protocol_key;
4085 	dpp_copy_csign(&auth->conf_obj[0], auth->conf->csign);
4086 
4087 	conf_obj = dpp_build_conf_obj(auth, ap, 0, NULL);
4088 	if (!conf_obj) {
4089 		wpabuf_free(auth->conf_obj[0].c_sign_key);
4090 		auth->conf_obj[0].c_sign_key = NULL;
4091 		goto fail;
4092 	}
4093 	ret = dpp_parse_conf_obj(auth, wpabuf_head(conf_obj),
4094 				 wpabuf_len(conf_obj));
4095 fail:
4096 	wpabuf_free(conf_obj);
4097 	auth->peer_protocol_key = NULL;
4098 	return ret;
4099 }
4100 
4101 
dpp_compatible_netrole(const char * role1,const char * role2)4102 static int dpp_compatible_netrole(const char *role1, const char *role2)
4103 {
4104 	return (os_strcmp(role1, "sta") == 0 && os_strcmp(role2, "ap") == 0) ||
4105 		(os_strcmp(role1, "ap") == 0 && os_strcmp(role2, "sta") == 0);
4106 }
4107 
4108 
dpp_connector_compatible_group(struct json_token * root,const char * group_id,const char * net_role,bool reconfig)4109 static int dpp_connector_compatible_group(struct json_token *root,
4110 					  const char *group_id,
4111 					  const char *net_role,
4112 					  bool reconfig)
4113 {
4114 	struct json_token *groups, *token;
4115 
4116 	groups = json_get_member(root, "groups");
4117 	if (!groups || groups->type != JSON_ARRAY)
4118 		return 0;
4119 
4120 	for (token = groups->child; token; token = token->sibling) {
4121 		struct json_token *id, *role;
4122 
4123 		id = json_get_member(token, "groupId");
4124 		if (!id || id->type != JSON_STRING)
4125 			continue;
4126 
4127 		role = json_get_member(token, "netRole");
4128 		if (!role || role->type != JSON_STRING)
4129 			continue;
4130 
4131 		if (os_strcmp(id->string, "*") != 0 &&
4132 		    os_strcmp(group_id, "*") != 0 &&
4133 		    os_strcmp(id->string, group_id) != 0)
4134 			continue;
4135 
4136 		if (reconfig && os_strcmp(net_role, "configurator") == 0)
4137 			return 1;
4138 		if (!reconfig && dpp_compatible_netrole(role->string, net_role))
4139 			return 1;
4140 	}
4141 
4142 	return 0;
4143 }
4144 
4145 
dpp_connector_match_groups(struct json_token * own_root,struct json_token * peer_root,bool reconfig)4146 int dpp_connector_match_groups(struct json_token *own_root,
4147 			       struct json_token *peer_root, bool reconfig)
4148 {
4149 	struct json_token *groups, *token;
4150 
4151 	groups = json_get_member(peer_root, "groups");
4152 	if (!groups || groups->type != JSON_ARRAY) {
4153 		wpa_printf(MSG_DEBUG, "DPP: No peer groups array found");
4154 		return 0;
4155 	}
4156 
4157 	for (token = groups->child; token; token = token->sibling) {
4158 		struct json_token *id, *role;
4159 
4160 		id = json_get_member(token, "groupId");
4161 		if (!id || id->type != JSON_STRING) {
4162 			wpa_printf(MSG_DEBUG,
4163 				   "DPP: Missing peer groupId string");
4164 			continue;
4165 		}
4166 
4167 		role = json_get_member(token, "netRole");
4168 		if (!role || role->type != JSON_STRING) {
4169 			wpa_printf(MSG_DEBUG,
4170 				   "DPP: Missing peer groups::netRole string");
4171 			continue;
4172 		}
4173 		wpa_printf(MSG_DEBUG,
4174 			   "DPP: peer connector group: groupId='%s' netRole='%s'",
4175 			   id->string, role->string);
4176 		if (dpp_connector_compatible_group(own_root, id->string,
4177 						   role->string, reconfig)) {
4178 			wpa_printf(MSG_DEBUG,
4179 				   "DPP: Compatible group/netRole in own connector");
4180 			return 1;
4181 		}
4182 	}
4183 
4184 	return 0;
4185 }
4186 
4187 
dpp_parse_own_connector(const char * own_connector)4188 struct json_token * dpp_parse_own_connector(const char *own_connector)
4189 {
4190 	unsigned char *own_conn;
4191 	size_t own_conn_len;
4192 	const char *pos, *end;
4193 	struct json_token *own_root;
4194 
4195 	pos = os_strchr(own_connector, '.');
4196 	if (!pos) {
4197 		wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the first dot (.)");
4198 		return NULL;
4199 	}
4200 	pos++;
4201 	end = os_strchr(pos, '.');
4202 	if (!end) {
4203 		wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the second dot (.)");
4204 		return NULL;
4205 	}
4206 	own_conn = base64_url_decode(pos, end - pos, &own_conn_len);
4207 	if (!own_conn) {
4208 		wpa_printf(MSG_DEBUG,
4209 			   "DPP: Failed to base64url decode own signedConnector JWS Payload");
4210 		return NULL;
4211 	}
4212 
4213 	own_root = json_parse((const char *) own_conn, own_conn_len);
4214 	os_free(own_conn);
4215 	if (!own_root)
4216 		wpa_printf(MSG_DEBUG, "DPP: Failed to parse local connector");
4217 
4218 	return own_root;
4219 }
4220 
4221 
4222 enum dpp_status_error
dpp_peer_intro(struct dpp_introduction * intro,const char * own_connector,const u8 * net_access_key,size_t net_access_key_len,const u8 * csign_key,size_t csign_key_len,const u8 * peer_connector,size_t peer_connector_len,os_time_t * expiry,u8 * peer_key_hash)4223 dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
4224 	       const u8 *net_access_key, size_t net_access_key_len,
4225 	       const u8 *csign_key, size_t csign_key_len,
4226 	       const u8 *peer_connector, size_t peer_connector_len,
4227 	       os_time_t *expiry, u8 *peer_key_hash)
4228 {
4229 	struct json_token *root = NULL, *netkey, *token;
4230 	struct json_token *own_root = NULL;
4231 	enum dpp_status_error ret = 255, res;
4232 	struct crypto_ec_key *own_key = NULL;
4233 	struct wpabuf *own_key_pub = NULL;
4234 	const struct dpp_curve_params *curve, *own_curve;
4235 	struct dpp_signed_connector_info info;
4236 	size_t Nx_len;
4237 	u8 Nx[DPP_MAX_SHARED_SECRET_LEN];
4238 
4239 	os_memset(intro, 0, sizeof(*intro));
4240 	os_memset(&info, 0, sizeof(info));
4241 	if (expiry)
4242 		*expiry = 0;
4243 
4244 	own_key = dpp_set_keypair(&own_curve, net_access_key,
4245 				  net_access_key_len);
4246 	if (!own_key) {
4247 		wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
4248 		goto fail;
4249 	}
4250 
4251 	own_root = dpp_parse_own_connector(own_connector);
4252 	if (!own_root)
4253 		goto fail;
4254 
4255 	res = dpp_check_signed_connector(&info, csign_key, csign_key_len,
4256 					 peer_connector, peer_connector_len);
4257 	if (res != DPP_STATUS_OK) {
4258 		ret = res;
4259 		goto fail;
4260 	}
4261 
4262 	root = json_parse((const char *) info.payload, info.payload_len);
4263 	if (!root) {
4264 		wpa_printf(MSG_DEBUG, "DPP: JSON parsing of connector failed");
4265 		ret = DPP_STATUS_INVALID_CONNECTOR;
4266 		goto fail;
4267 	}
4268 
4269 	if (!dpp_connector_match_groups(own_root, root, false)) {
4270 		wpa_printf(MSG_DEBUG,
4271 			   "DPP: Peer connector does not include compatible group netrole with own connector");
4272 		ret = DPP_STATUS_NO_MATCH;
4273 		goto fail;
4274 	}
4275 
4276 	token = json_get_member(root, "expiry");
4277 	if (!token || token->type != JSON_STRING) {
4278 		wpa_printf(MSG_DEBUG,
4279 			   "DPP: No expiry string found - connector does not expire");
4280 	} else {
4281 		wpa_printf(MSG_DEBUG, "DPP: expiry = %s", token->string);
4282 		if (dpp_key_expired(token->string, expiry)) {
4283 			wpa_printf(MSG_DEBUG,
4284 				   "DPP: Connector (netAccessKey) has expired");
4285 			ret = DPP_STATUS_INVALID_CONNECTOR;
4286 			goto fail;
4287 		}
4288 	}
4289 
4290 #ifdef CONFIG_DPP3
4291 	token = json_get_member(root, "version");
4292 	if (token && token->type == JSON_NUMBER) {
4293 		wpa_printf(MSG_DEBUG, "DPP: version = %d", token->number);
4294 		intro->peer_version = token->number;
4295 	}
4296 #endif /* CONFIG_DPP3 */
4297 
4298 	netkey = json_get_member(root, "netAccessKey");
4299 	if (!netkey || netkey->type != JSON_OBJECT) {
4300 		wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
4301 		ret = DPP_STATUS_INVALID_CONNECTOR;
4302 		goto fail;
4303 	}
4304 
4305 	intro->peer_key = dpp_parse_jwk(netkey, &curve);
4306 	if (!intro->peer_key) {
4307 		ret = DPP_STATUS_INVALID_CONNECTOR;
4308 		goto fail;
4309 	}
4310 	dpp_debug_print_key("DPP: Received netAccessKey", intro->peer_key);
4311 
4312 	if (own_curve != curve) {
4313 		wpa_printf(MSG_DEBUG,
4314 			   "DPP: Mismatching netAccessKey curves (%s != %s)",
4315 			   own_curve->name, curve->name);
4316 		ret = DPP_STATUS_INVALID_CONNECTOR;
4317 		goto fail;
4318 	}
4319 
4320 	/* ECDH: N = nk * PK */
4321 	if (dpp_ecdh(own_key, intro->peer_key, Nx, &Nx_len) < 0)
4322 		goto fail;
4323 
4324 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
4325 			Nx, Nx_len);
4326 
4327 	/* PMK = HKDF(<>, "DPP PMK", N.x) */
4328 	if (dpp_derive_pmk(Nx, Nx_len, intro->pmk, curve->hash_len) < 0) {
4329 		wpa_printf(MSG_ERROR, "DPP: Failed to derive PMK");
4330 		goto fail;
4331 	}
4332 	intro->pmk_len = curve->hash_len;
4333 
4334 	/* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
4335 	if (dpp_derive_pmkid(curve, own_key, intro->peer_key, intro->pmkid) <
4336 	    0) {
4337 		wpa_printf(MSG_ERROR, "DPP: Failed to derive PMKID");
4338 		goto fail;
4339 	}
4340 
4341 #ifdef CONFIG_DPP3
4342 	if (dpp_hpke_suite(curve->ike_group, &intro->kem_id, &intro->kdf_id,
4343 			   &intro->aead_id) < 0) {
4344 		wpa_printf(MSG_ERROR, "DPP: Unsupported group %d",
4345 			   curve->ike_group);
4346 		goto fail;
4347 	}
4348 #endif /* CONFIG_DPP3 */
4349 
4350 	if (peer_key_hash)
4351 		dpp_get_pubkey_hash(intro->peer_key, peer_key_hash);
4352 
4353 	ret = DPP_STATUS_OK;
4354 fail:
4355 	if (ret != DPP_STATUS_OK)
4356 		dpp_peer_intro_deinit(intro);
4357 	os_memset(Nx, 0, sizeof(Nx));
4358 	os_free(info.payload);
4359 	crypto_ec_key_deinit(own_key);
4360 	wpabuf_free(own_key_pub);
4361 	json_free(root);
4362 	json_free(own_root);
4363 	return ret;
4364 }
4365 
4366 
dpp_peer_intro_deinit(struct dpp_introduction * intro)4367 void dpp_peer_intro_deinit(struct dpp_introduction *intro)
4368 {
4369 	if (!intro)
4370 		return;
4371 
4372 	crypto_ec_key_deinit(intro->peer_key);
4373 	os_memset(intro, 0, sizeof(*intro));
4374 }
4375 
4376 
4377 #ifdef CONFIG_DPP3
dpp_get_connector_version(const char * connector)4378 int dpp_get_connector_version(const char *connector)
4379 {
4380 	struct json_token *root, *token;
4381 	int ver = -1;
4382 
4383 	root = dpp_parse_own_connector(connector);
4384 	if (!root)
4385 		return -1;
4386 
4387 	token = json_get_member(root, "version");
4388 	if (token && token->type == JSON_NUMBER)
4389 		ver = token->number;
4390 
4391 	json_free(root);
4392 	return ver;
4393 }
4394 #endif /* CONFIG_DPP3 */
4395 
4396 
dpp_next_id(struct dpp_global * dpp)4397 unsigned int dpp_next_id(struct dpp_global *dpp)
4398 {
4399 	struct dpp_bootstrap_info *bi;
4400 	unsigned int max_id = 0;
4401 
4402 	dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
4403 		if (bi->id > max_id)
4404 			max_id = bi->id;
4405 	}
4406 	return max_id + 1;
4407 }
4408 
4409 
dpp_bootstrap_del(struct dpp_global * dpp,unsigned int id)4410 static int dpp_bootstrap_del(struct dpp_global *dpp, unsigned int id)
4411 {
4412 	struct dpp_bootstrap_info *bi, *tmp;
4413 	int found = 0;
4414 
4415 	if (!dpp)
4416 		return -1;
4417 
4418 	dl_list_for_each_safe(bi, tmp, &dpp->bootstrap,
4419 			      struct dpp_bootstrap_info, list) {
4420 		if (id && bi->id != id)
4421 			continue;
4422 		found = 1;
4423 #ifdef CONFIG_DPP2
4424 		if (dpp->remove_bi)
4425 			dpp->remove_bi(dpp->cb_ctx, bi);
4426 #endif /* CONFIG_DPP2 */
4427 		dl_list_del(&bi->list);
4428 		dpp_bootstrap_info_free(bi);
4429 	}
4430 
4431 	if (id == 0)
4432 		return 0; /* flush succeeds regardless of entries found */
4433 	return found ? 0 : -1;
4434 }
4435 
4436 
dpp_add_qr_code(struct dpp_global * dpp,const char * uri)4437 struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp,
4438 					    const char *uri)
4439 {
4440 	struct dpp_bootstrap_info *bi;
4441 
4442 	if (!dpp)
4443 		return NULL;
4444 
4445 	bi = dpp_parse_uri(uri);
4446 	if (!bi)
4447 		return NULL;
4448 
4449 	bi->type = DPP_BOOTSTRAP_QR_CODE;
4450 	bi->id = dpp_next_id(dpp);
4451 	dl_list_add(&dpp->bootstrap, &bi->list);
4452 	return bi;
4453 }
4454 
4455 
dpp_add_nfc_uri(struct dpp_global * dpp,const char * uri)4456 struct dpp_bootstrap_info * dpp_add_nfc_uri(struct dpp_global *dpp,
4457 					    const char *uri)
4458 {
4459 	struct dpp_bootstrap_info *bi;
4460 
4461 	if (!dpp)
4462 		return NULL;
4463 
4464 	bi = dpp_parse_uri(uri);
4465 	if (!bi)
4466 		return NULL;
4467 
4468 	bi->type = DPP_BOOTSTRAP_NFC_URI;
4469 	bi->id = dpp_next_id(dpp);
4470 	dl_list_add(&dpp->bootstrap, &bi->list);
4471 	return bi;
4472 }
4473 
4474 
dpp_parse_supported_curves_list(struct dpp_bootstrap_info * bi,char * txt)4475 static int dpp_parse_supported_curves_list(struct dpp_bootstrap_info *bi,
4476 					   char *txt)
4477 {
4478 	char *token, *context = NULL;
4479 	u8 curves = 0;
4480 
4481 	if (!txt)
4482 		return 0;
4483 
4484 	while ((token = str_token(txt, ":", &context))) {
4485 		if (os_strcmp(token, "P-256") == 0) {
4486 			curves |= BIT(DPP_BOOTSTRAP_CURVE_P_256);
4487 		} else if (os_strcmp(token, "P-384") == 0) {
4488 			curves |= BIT(DPP_BOOTSTRAP_CURVE_P_384);
4489 		} else if (os_strcmp(token, "P-521") == 0) {
4490 			curves |= BIT(DPP_BOOTSTRAP_CURVE_P_521);
4491 		} else if (os_strcmp(token, "BP-256") == 0) {
4492 			curves |= BIT(DPP_BOOTSTRAP_CURVE_BP_256);
4493 		} else if (os_strcmp(token, "BP-384") == 0) {
4494 			curves |= BIT(DPP_BOOTSTRAP_CURVE_BP_384);
4495 		} else if (os_strcmp(token, "BP-512") == 0) {
4496 			curves |= BIT(DPP_BOOTSTRAP_CURVE_BP_512);
4497 		} else {
4498 			wpa_printf(MSG_DEBUG, "DPP: Unsupported curve '%s'",
4499 				   token);
4500 			return -1;
4501 		}
4502 	}
4503 	bi->supported_curves = curves;
4504 
4505 	wpa_printf(MSG_DEBUG, "DPP: URI supported curves: 0x%x",
4506 		   bi->supported_curves);
4507 
4508 	return 0;
4509 }
4510 
4511 
dpp_bootstrap_gen(struct dpp_global * dpp,const char * cmd)4512 int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd)
4513 {
4514 	char *mac = NULL, *info = NULL, *curve = NULL;
4515 	char *key = NULL, *supported_curves = NULL, *host = NULL;
4516 	u8 *privkey = NULL;
4517 	size_t privkey_len = 0;
4518 	int ret = -1;
4519 	struct dpp_bootstrap_info *bi;
4520 
4521 	if (!dpp)
4522 		return -1;
4523 
4524 	bi = os_zalloc(sizeof(*bi));
4525 	if (!bi)
4526 		goto fail;
4527 
4528 	if (os_strstr(cmd, "type=qrcode"))
4529 		bi->type = DPP_BOOTSTRAP_QR_CODE;
4530 	else if (os_strstr(cmd, "type=pkex"))
4531 		bi->type = DPP_BOOTSTRAP_PKEX;
4532 	else if (os_strstr(cmd, "type=nfc-uri"))
4533 		bi->type = DPP_BOOTSTRAP_NFC_URI;
4534 	else
4535 		goto fail;
4536 
4537 	bi->chan = get_param(cmd, " chan=");
4538 	mac = get_param(cmd, " mac=");
4539 	info = get_param(cmd, " info=");
4540 	curve = get_param(cmd, " curve=");
4541 	key = get_param(cmd, " key=");
4542 	supported_curves = get_param(cmd, " supported_curves=");
4543 	host = get_param(cmd, " host=");
4544 
4545 	if (key) {
4546 		privkey_len = os_strlen(key) / 2;
4547 		privkey = os_malloc(privkey_len);
4548 		if (!privkey ||
4549 		    hexstr2bin(key, privkey, privkey_len) < 0)
4550 			goto fail;
4551 	}
4552 
4553 	if (dpp_keygen(bi, curve, privkey, privkey_len) < 0 ||
4554 	    dpp_parse_uri_chan_list(bi, bi->chan) < 0 ||
4555 	    dpp_parse_uri_mac(bi, mac) < 0 ||
4556 	    dpp_parse_uri_info(bi, info) < 0 ||
4557 	    dpp_parse_supported_curves_list(bi, supported_curves) < 0 ||
4558 	    dpp_parse_uri_host(bi, host) < 0 ||
4559 	    dpp_gen_uri(bi) < 0)
4560 		goto fail;
4561 
4562 	bi->id = dpp_next_id(dpp);
4563 	dl_list_add(&dpp->bootstrap, &bi->list);
4564 	ret = bi->id;
4565 	bi = NULL;
4566 fail:
4567 	os_free(curve);
4568 	os_free(mac);
4569 	os_free(info);
4570 	str_clear_free(key);
4571 	os_free(supported_curves);
4572 	os_free(host);
4573 	bin_clear_free(privkey, privkey_len);
4574 	dpp_bootstrap_info_free(bi);
4575 	return ret;
4576 }
4577 
4578 
4579 struct dpp_bootstrap_info *
dpp_bootstrap_get_id(struct dpp_global * dpp,unsigned int id)4580 dpp_bootstrap_get_id(struct dpp_global *dpp, unsigned int id)
4581 {
4582 	struct dpp_bootstrap_info *bi;
4583 
4584 	if (!dpp)
4585 		return NULL;
4586 
4587 	dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
4588 		if (bi->id == id)
4589 			return bi;
4590 	}
4591 	return NULL;
4592 }
4593 
4594 
dpp_bootstrap_remove(struct dpp_global * dpp,const char * id)4595 int dpp_bootstrap_remove(struct dpp_global *dpp, const char *id)
4596 {
4597 	unsigned int id_val;
4598 
4599 	if (os_strcmp(id, "*") == 0) {
4600 		id_val = 0;
4601 	} else {
4602 		id_val = atoi(id);
4603 		if (id_val == 0)
4604 			return -1;
4605 	}
4606 
4607 	return dpp_bootstrap_del(dpp, id_val);
4608 }
4609 
4610 
dpp_bootstrap_get_uri(struct dpp_global * dpp,unsigned int id)4611 const char * dpp_bootstrap_get_uri(struct dpp_global *dpp, unsigned int id)
4612 {
4613 	struct dpp_bootstrap_info *bi;
4614 
4615 	bi = dpp_bootstrap_get_id(dpp, id);
4616 	if (!bi)
4617 		return NULL;
4618 	return bi->uri;
4619 }
4620 
4621 
dpp_bootstrap_info(struct dpp_global * dpp,int id,char * reply,int reply_size)4622 int dpp_bootstrap_info(struct dpp_global *dpp, int id,
4623 		       char *reply, int reply_size)
4624 {
4625 	struct dpp_bootstrap_info *bi;
4626 	char pkhash[2 * SHA256_MAC_LEN + 1];
4627 	char supp_curves[100];
4628 	char host[100];
4629 	int ret;
4630 
4631 	bi = dpp_bootstrap_get_id(dpp, id);
4632 	if (!bi)
4633 		return -1;
4634 	wpa_snprintf_hex(pkhash, sizeof(pkhash), bi->pubkey_hash,
4635 			 SHA256_MAC_LEN);
4636 
4637 	supp_curves[0] = '\0';
4638 	if (bi->supported_curves) {
4639 		size_t i;
4640 		char *pos = supp_curves;
4641 		char *end = &supp_curves[sizeof(supp_curves)];
4642 		const char *curve[6] = { "P-256", "P-384", "P-521",
4643 					 "BP-256", "BP-384", "BP-512" };
4644 
4645 		ret = os_snprintf(pos, end - pos, "supp_curves=");
4646 		if (os_snprintf_error(end - pos, ret))
4647 			return -1;
4648 		pos += ret;
4649 
4650 		for (i = 0; i < ARRAY_SIZE(curve); i++) {
4651 			if (!(bi->supported_curves & BIT(i)))
4652 				continue;
4653 			ret = os_snprintf(pos, end - pos, "%s:", curve[i]);
4654 			if (os_snprintf_error(end - pos, ret))
4655 				return -1;
4656 			pos += ret;
4657 		}
4658 
4659 		if (pos[-1] == ':')
4660 			pos[-1] = '\n';
4661 		else
4662 			supp_curves[0] = '\0';
4663 	}
4664 
4665 	host[0] = '\0';
4666 	if (bi->host) {
4667 		char buf[100];
4668 
4669 		ret = os_snprintf(host, sizeof(host), "host=%s %u\n",
4670 				  hostapd_ip_txt(bi->host, buf, sizeof(buf)),
4671 				  bi->port);
4672 		if (os_snprintf_error(sizeof(host), ret))
4673 			return -1;
4674 	}
4675 
4676 	return os_snprintf(reply, reply_size, "type=%s\n"
4677 			   "mac_addr=" MACSTR "\n"
4678 			   "info=%s\n"
4679 			   "num_freq=%u\n"
4680 			   "use_freq=%u\n"
4681 			   "curve=%s\n"
4682 			   "pkhash=%s\n"
4683 			   "version=%d\n%s%s",
4684 			   dpp_bootstrap_type_txt(bi->type),
4685 			   MAC2STR(bi->mac_addr),
4686 			   bi->info ? bi->info : "",
4687 			   bi->num_freq,
4688 			   bi->num_freq == 1 ? bi->freq[0] : 0,
4689 			   bi->curve->name,
4690 			   pkhash,
4691 			   bi->version,
4692 			   supp_curves,
4693 			   host);
4694 }
4695 
4696 
dpp_bootstrap_set(struct dpp_global * dpp,int id,const char * params)4697 int dpp_bootstrap_set(struct dpp_global *dpp, int id, const char *params)
4698 {
4699 	struct dpp_bootstrap_info *bi;
4700 
4701 	bi = dpp_bootstrap_get_id(dpp, id);
4702 	if (!bi)
4703 		return -1;
4704 
4705 	str_clear_free(bi->configurator_params);
4706 
4707 	if (params) {
4708 		bi->configurator_params = os_strdup(params);
4709 		return bi->configurator_params ? 0 : -1;
4710 	}
4711 
4712 	bi->configurator_params = NULL;
4713 	return 0;
4714 }
4715 
4716 
dpp_bootstrap_find_pair(struct dpp_global * dpp,const u8 * i_bootstrap,const u8 * r_bootstrap,struct dpp_bootstrap_info ** own_bi,struct dpp_bootstrap_info ** peer_bi)4717 void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap,
4718 			     const u8 *r_bootstrap,
4719 			     struct dpp_bootstrap_info **own_bi,
4720 			     struct dpp_bootstrap_info **peer_bi)
4721 {
4722 	struct dpp_bootstrap_info *bi;
4723 
4724 	*own_bi = NULL;
4725 	*peer_bi = NULL;
4726 	if (!dpp)
4727 		return;
4728 
4729 	dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
4730 		if (!*own_bi && bi->own &&
4731 		    os_memcmp(bi->pubkey_hash, r_bootstrap,
4732 			      SHA256_MAC_LEN) == 0) {
4733 			wpa_printf(MSG_DEBUG,
4734 				   "DPP: Found matching own bootstrapping information");
4735 			*own_bi = bi;
4736 		}
4737 
4738 		if (!*peer_bi && !bi->own &&
4739 		    os_memcmp(bi->pubkey_hash, i_bootstrap,
4740 			      SHA256_MAC_LEN) == 0) {
4741 			wpa_printf(MSG_DEBUG,
4742 				   "DPP: Found matching peer bootstrapping information");
4743 			*peer_bi = bi;
4744 		}
4745 
4746 		if (*own_bi && *peer_bi)
4747 			break;
4748 	}
4749 }
4750 
4751 
4752 #ifdef CONFIG_DPP2
dpp_bootstrap_find_chirp(struct dpp_global * dpp,const u8 * hash)4753 struct dpp_bootstrap_info * dpp_bootstrap_find_chirp(struct dpp_global *dpp,
4754 						     const u8 *hash)
4755 {
4756 	struct dpp_bootstrap_info *bi;
4757 
4758 	if (!dpp)
4759 		return NULL;
4760 
4761 	dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) {
4762 		if (!bi->own && os_memcmp(bi->pubkey_hash_chirp, hash,
4763 					  SHA256_MAC_LEN) == 0)
4764 			return bi;
4765 	}
4766 
4767 	return NULL;
4768 }
4769 #endif /* CONFIG_DPP2 */
4770 
4771 
dpp_nfc_update_bi_channel(struct dpp_bootstrap_info * own_bi,struct dpp_bootstrap_info * peer_bi)4772 static int dpp_nfc_update_bi_channel(struct dpp_bootstrap_info *own_bi,
4773 				     struct dpp_bootstrap_info *peer_bi)
4774 {
4775 	unsigned int i, freq = 0;
4776 	enum hostapd_hw_mode mode;
4777 	u8 op_class, channel;
4778 	char chan[20];
4779 
4780 	if (peer_bi->num_freq == 0 && !peer_bi->channels_listed)
4781 		return 0; /* no channel preference/constraint */
4782 
4783 	for (i = 0; i < peer_bi->num_freq; i++) {
4784 		if ((own_bi->num_freq == 0 && !own_bi->channels_listed) ||
4785 		    freq_included(own_bi->freq, own_bi->num_freq,
4786 				  peer_bi->freq[i])) {
4787 			freq = peer_bi->freq[i];
4788 			break;
4789 		}
4790 	}
4791 	if (!freq) {
4792 		wpa_printf(MSG_DEBUG, "DPP: No common channel found");
4793 		return -1;
4794 	}
4795 
4796 	mode = ieee80211_freq_to_channel_ext(freq, 0, 0, &op_class, &channel);
4797 	if (mode == NUM_HOSTAPD_MODES) {
4798 		wpa_printf(MSG_DEBUG,
4799 			   "DPP: Could not determine operating class or channel number for %u MHz",
4800 			   freq);
4801 	}
4802 
4803 	wpa_printf(MSG_DEBUG,
4804 		   "DPP: Selected %u MHz (op_class %u channel %u) as the negotiation channel based on information from NFC negotiated handover",
4805 		   freq, op_class, channel);
4806 	os_snprintf(chan, sizeof(chan), "%u/%u", op_class, channel);
4807 	os_free(own_bi->chan);
4808 	own_bi->chan = os_strdup(chan);
4809 	own_bi->freq[0] = freq;
4810 	own_bi->num_freq = 1;
4811 	os_free(peer_bi->chan);
4812 	peer_bi->chan = os_strdup(chan);
4813 	peer_bi->freq[0] = freq;
4814 	peer_bi->num_freq = 1;
4815 
4816 	return dpp_gen_uri(own_bi);
4817 }
4818 
4819 
dpp_nfc_update_bi_key(struct dpp_bootstrap_info * own_bi,struct dpp_bootstrap_info * peer_bi)4820 static int dpp_nfc_update_bi_key(struct dpp_bootstrap_info *own_bi,
4821 				 struct dpp_bootstrap_info *peer_bi)
4822 {
4823 	if (peer_bi->curve == own_bi->curve)
4824 		return 0;
4825 
4826 	wpa_printf(MSG_DEBUG,
4827 		   "DPP: Update own bootstrapping key to match peer curve from NFC handover");
4828 
4829 	crypto_ec_key_deinit(own_bi->pubkey);
4830 	own_bi->pubkey = NULL;
4831 
4832 	if (dpp_keygen(own_bi, peer_bi->curve->name, NULL, 0) < 0 ||
4833 	    dpp_gen_uri(own_bi) < 0)
4834 		goto fail;
4835 
4836 	return 0;
4837 fail:
4838 	dl_list_del(&own_bi->list);
4839 	dpp_bootstrap_info_free(own_bi);
4840 	return -1;
4841 }
4842 
4843 
dpp_nfc_update_bi(struct dpp_bootstrap_info * own_bi,struct dpp_bootstrap_info * peer_bi)4844 int dpp_nfc_update_bi(struct dpp_bootstrap_info *own_bi,
4845 		      struct dpp_bootstrap_info *peer_bi)
4846 {
4847 	if (dpp_nfc_update_bi_channel(own_bi, peer_bi) < 0 ||
4848 	    dpp_nfc_update_bi_key(own_bi, peer_bi) < 0)
4849 		return -1;
4850 	return 0;
4851 }
4852 
4853 
dpp_next_configurator_id(struct dpp_global * dpp)4854 static unsigned int dpp_next_configurator_id(struct dpp_global *dpp)
4855 {
4856 	struct dpp_configurator *conf;
4857 	unsigned int max_id = 0;
4858 
4859 	dl_list_for_each(conf, &dpp->configurator, struct dpp_configurator,
4860 			 list) {
4861 		if (conf->id > max_id)
4862 			max_id = conf->id;
4863 	}
4864 	return max_id + 1;
4865 }
4866 
4867 
dpp_configurator_add(struct dpp_global * dpp,const char * cmd)4868 int dpp_configurator_add(struct dpp_global *dpp, const char *cmd)
4869 {
4870 	char *curve;
4871 	char *key = NULL, *ppkey = NULL;
4872 	u8 *privkey = NULL, *pp_key = NULL;
4873 	size_t privkey_len = 0, pp_key_len = 0;
4874 	int ret = -1;
4875 	struct dpp_configurator *conf = NULL;
4876 	const struct dpp_curve_params *net_access_key_curve = NULL;
4877 
4878 	curve = get_param(cmd, " net_access_key_curve=");
4879 	if (curve) {
4880 		net_access_key_curve = dpp_get_curve_name(curve);
4881 		if (!net_access_key_curve) {
4882 			wpa_printf(MSG_DEBUG,
4883 				   "DPP: Unsupported net_access_key_curve: %s",
4884 				   curve);
4885 			goto fail;
4886 		}
4887 		os_free(curve);
4888 	}
4889 
4890 	curve = get_param(cmd, " curve=");
4891 	key = get_param(cmd, " key=");
4892 	ppkey = get_param(cmd, " ppkey=");
4893 
4894 	if (key) {
4895 		privkey_len = os_strlen(key) / 2;
4896 		privkey = os_malloc(privkey_len);
4897 		if (!privkey ||
4898 		    hexstr2bin(key, privkey, privkey_len) < 0)
4899 			goto fail;
4900 	}
4901 
4902 	if (ppkey) {
4903 		pp_key_len = os_strlen(ppkey) / 2;
4904 		pp_key = os_malloc(pp_key_len);
4905 		if (!pp_key ||
4906 		    hexstr2bin(ppkey, pp_key, pp_key_len) < 0)
4907 			goto fail;
4908 	}
4909 
4910 	conf = dpp_keygen_configurator(curve, privkey, privkey_len,
4911 				       pp_key, pp_key_len);
4912 	if (!conf)
4913 		goto fail;
4914 
4915 	conf->net_access_key_curve = net_access_key_curve;
4916 	conf->id = dpp_next_configurator_id(dpp);
4917 	dl_list_add(&dpp->configurator, &conf->list);
4918 	ret = conf->id;
4919 	conf = NULL;
4920 fail:
4921 	os_free(curve);
4922 	str_clear_free(key);
4923 	str_clear_free(ppkey);
4924 	bin_clear_free(privkey, privkey_len);
4925 	bin_clear_free(pp_key, pp_key_len);
4926 	dpp_configurator_free(conf);
4927 	return ret;
4928 }
4929 
4930 
dpp_configurator_set(struct dpp_global * dpp,const char * cmd)4931 int dpp_configurator_set(struct dpp_global *dpp, const char *cmd)
4932 {
4933 	unsigned int id;
4934 	struct dpp_configurator *conf;
4935 	char *curve;
4936 
4937 	id = atoi(cmd);
4938 	conf = dpp_configurator_get_id(dpp, id);
4939 	if (!conf)
4940 		return -1;
4941 
4942 	curve = get_param(cmd, " net_access_key_curve=");
4943 	if (curve) {
4944 		const struct dpp_curve_params *net_access_key_curve;
4945 
4946 		net_access_key_curve = dpp_get_curve_name(curve);
4947 		os_free(curve);
4948 		if (!net_access_key_curve)
4949 			return -1;
4950 		conf->net_access_key_curve = net_access_key_curve;
4951 	}
4952 
4953 	return 0;
4954 }
4955 
4956 
dpp_configurator_del(struct dpp_global * dpp,unsigned int id)4957 static int dpp_configurator_del(struct dpp_global *dpp, unsigned int id)
4958 {
4959 	struct dpp_configurator *conf, *tmp;
4960 	int found = 0;
4961 
4962 	if (!dpp)
4963 		return -1;
4964 
4965 	dl_list_for_each_safe(conf, tmp, &dpp->configurator,
4966 			      struct dpp_configurator, list) {
4967 		if (id && conf->id != id)
4968 			continue;
4969 		found = 1;
4970 		dl_list_del(&conf->list);
4971 		dpp_configurator_free(conf);
4972 	}
4973 
4974 	if (id == 0)
4975 		return 0; /* flush succeeds regardless of entries found */
4976 	return found ? 0 : -1;
4977 }
4978 
4979 
dpp_configurator_remove(struct dpp_global * dpp,const char * id)4980 int dpp_configurator_remove(struct dpp_global *dpp, const char *id)
4981 {
4982 	unsigned int id_val;
4983 
4984 	if (os_strcmp(id, "*") == 0) {
4985 		id_val = 0;
4986 	} else {
4987 		id_val = atoi(id);
4988 		if (id_val == 0)
4989 			return -1;
4990 	}
4991 
4992 	return dpp_configurator_del(dpp, id_val);
4993 }
4994 
4995 
dpp_configurator_get_key_id(struct dpp_global * dpp,unsigned int id,char * buf,size_t buflen)4996 int dpp_configurator_get_key_id(struct dpp_global *dpp, unsigned int id,
4997 				char *buf, size_t buflen)
4998 {
4999 	struct dpp_configurator *conf;
5000 
5001 	conf = dpp_configurator_get_id(dpp, id);
5002 	if (!conf)
5003 		return -1;
5004 
5005 	return dpp_configurator_get_key(conf, buf, buflen);
5006 }
5007 
5008 
5009 #ifdef CONFIG_DPP2
5010 
dpp_configurator_from_backup(struct dpp_global * dpp,struct dpp_asymmetric_key * key)5011 int dpp_configurator_from_backup(struct dpp_global *dpp,
5012 				 struct dpp_asymmetric_key *key)
5013 {
5014 	struct dpp_configurator *conf;
5015 	const struct dpp_curve_params *curve, *curve_pp;
5016 
5017 	if (!key->csign || !key->pp_key)
5018 		return -1;
5019 
5020 	curve = dpp_get_curve_ike_group(crypto_ec_key_group(key->csign));
5021 	if (!curve) {
5022 		wpa_printf(MSG_INFO, "DPP: Unsupported group in c-sign-key");
5023 		return -1;
5024 	}
5025 
5026 	curve_pp = dpp_get_curve_ike_group(crypto_ec_key_group(key->pp_key));
5027 	if (!curve_pp) {
5028 		wpa_printf(MSG_INFO, "DPP: Unsupported group in ppKey");
5029 		return -1;
5030 	}
5031 
5032 	if (curve != curve_pp) {
5033 		wpa_printf(MSG_INFO,
5034 			   "DPP: Mismatch in c-sign-key and ppKey groups");
5035 		return -1;
5036 	}
5037 
5038 	conf = os_zalloc(sizeof(*conf));
5039 	if (!conf)
5040 		return -1;
5041 	conf->curve = curve;
5042 	conf->csign = key->csign;
5043 	key->csign = NULL;
5044 	conf->pp_key = key->pp_key;
5045 	key->pp_key = NULL;
5046 	conf->own = 1;
5047 	if (dpp_configurator_gen_kid(conf) < 0) {
5048 		dpp_configurator_free(conf);
5049 		return -1;
5050 	}
5051 
5052 	conf->id = dpp_next_configurator_id(dpp);
5053 	dl_list_add(&dpp->configurator, &conf->list);
5054 	return conf->id;
5055 }
5056 
5057 
dpp_configurator_find_kid(struct dpp_global * dpp,const u8 * kid)5058 struct dpp_configurator * dpp_configurator_find_kid(struct dpp_global *dpp,
5059 						    const u8 *kid)
5060 {
5061 	struct dpp_configurator *conf;
5062 
5063 	if (!dpp)
5064 		return NULL;
5065 
5066 	dl_list_for_each(conf, &dpp->configurator,
5067 			 struct dpp_configurator, list) {
5068 		if (os_memcmp(conf->kid_hash, kid, SHA256_MAC_LEN) == 0)
5069 			return conf;
5070 	}
5071 	return NULL;
5072 }
5073 
5074 #endif /* CONFIG_DPP2 */
5075 
5076 
dpp_global_init(struct dpp_global_config * config)5077 struct dpp_global * dpp_global_init(struct dpp_global_config *config)
5078 {
5079 	struct dpp_global *dpp;
5080 
5081 	dpp = os_zalloc(sizeof(*dpp));
5082 	if (!dpp)
5083 		return NULL;
5084 #ifdef CONFIG_DPP2
5085 	dpp->cb_ctx = config->cb_ctx;
5086 	dpp->remove_bi = config->remove_bi;
5087 #endif /* CONFIG_DPP2 */
5088 
5089 	dl_list_init(&dpp->bootstrap);
5090 	dl_list_init(&dpp->configurator);
5091 #ifdef CONFIG_DPP2
5092 	dl_list_init(&dpp->controllers);
5093 	dl_list_init(&dpp->tcp_init);
5094 	dpp->relay_sock = -1;
5095 #endif /* CONFIG_DPP2 */
5096 
5097 	return dpp;
5098 }
5099 
5100 
dpp_global_clear(struct dpp_global * dpp)5101 void dpp_global_clear(struct dpp_global *dpp)
5102 {
5103 	if (!dpp)
5104 		return;
5105 
5106 	dpp_bootstrap_del(dpp, 0);
5107 	dpp_configurator_del(dpp, 0);
5108 #ifdef CONFIG_DPP2
5109 	dpp_tcp_init_flush(dpp);
5110 	dpp_relay_flush_controllers(dpp);
5111 	dpp_controller_stop(dpp);
5112 #endif /* CONFIG_DPP2 */
5113 }
5114 
5115 
dpp_global_deinit(struct dpp_global * dpp)5116 void dpp_global_deinit(struct dpp_global *dpp)
5117 {
5118 	dpp_global_clear(dpp);
5119 	os_free(dpp);
5120 }
5121 
5122 
dpp_notify_auth_success(struct dpp_authentication * auth,int initiator)5123 void dpp_notify_auth_success(struct dpp_authentication *auth, int initiator)
5124 {
5125 	u8 hash[SHA256_MAC_LEN];
5126 	char hex[SHA256_MAC_LEN * 2 + 1];
5127 
5128 	if (auth->peer_protocol_key) {
5129 		dpp_get_pubkey_hash(auth->peer_protocol_key, hash);
5130 		wpa_snprintf_hex(hex, sizeof(hex), hash, sizeof(hash));
5131 	} else {
5132 		hex[0] = '\0';
5133 	}
5134 	wpa_msg(auth->msg_ctx, MSG_INFO,
5135 		DPP_EVENT_AUTH_SUCCESS "init=%d pkhash=%s own=%d peer=%d",
5136 		initiator, hex, auth->own_bi ? (int) auth->own_bi->id : -1,
5137 		auth->peer_bi ? (int) auth->peer_bi->id : -1);
5138 }
5139 
5140 
5141 #ifdef CONFIG_DPP2
5142 
dpp_build_presence_announcement(struct dpp_bootstrap_info * bi)5143 struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi)
5144 {
5145 	struct wpabuf *msg;
5146 
5147 	wpa_printf(MSG_DEBUG, "DPP: Build Presence Announcement frame");
5148 
5149 	msg = dpp_alloc_msg(DPP_PA_PRESENCE_ANNOUNCEMENT, 4 + SHA256_MAC_LEN);
5150 	if (!msg)
5151 		return NULL;
5152 
5153 	/* Responder Bootstrapping Key Hash */
5154 	dpp_build_attr_r_bootstrap_key_hash(msg, bi->pubkey_hash_chirp);
5155 	wpa_hexdump_buf(MSG_DEBUG,
5156 			"DPP: Presence Announcement frame attributes", msg);
5157 	return msg;
5158 }
5159 
5160 
dpp_notify_chirp_received(void * msg_ctx,int id,const u8 * src,unsigned int freq,const u8 * hash)5161 void dpp_notify_chirp_received(void *msg_ctx, int id, const u8 *src,
5162 				unsigned int freq, const u8 *hash)
5163 {
5164 	char hex[SHA256_MAC_LEN * 2 + 1];
5165 
5166 	wpa_snprintf_hex(hex, sizeof(hex), hash, SHA256_MAC_LEN);
5167 	wpa_msg(msg_ctx, MSG_INFO,
5168 		DPP_EVENT_CHIRP_RX "id=%d src=" MACSTR " freq=%u hash=%s",
5169 		id, MAC2STR(src), freq, hex);
5170 }
5171 
5172 #endif /* CONFIG_DPP2 */
5173 
5174 
5175 #ifdef CONFIG_DPP3
5176 
dpp_build_pb_announcement(struct dpp_bootstrap_info * bi)5177 struct wpabuf * dpp_build_pb_announcement(struct dpp_bootstrap_info *bi)
5178 {
5179 	struct wpabuf *msg;
5180 	const u8 *r_hash = bi->pubkey_hash_chirp;
5181 #ifdef CONFIG_TESTING_OPTIONS
5182 	u8 test_hash[SHA256_MAC_LEN];
5183 #endif /* CONFIG_TESTING_OPTIONS */
5184 
5185 	wpa_printf(MSG_DEBUG,
5186 		   "DPP: Build Push Button Presence Announcement frame");
5187 
5188 	msg = dpp_alloc_msg(DPP_PA_PB_PRESENCE_ANNOUNCEMENT,
5189 			    4 + SHA256_MAC_LEN);
5190 	if (!msg)
5191 		return NULL;
5192 
5193 #ifdef CONFIG_TESTING_OPTIONS
5194 	if (dpp_test == DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_PB_REQ) {
5195 		wpa_printf(MSG_INFO,
5196 			   "DPP: TESTING - invalid R-Bootstrap Key Hash");
5197 		os_memcpy(test_hash, r_hash, SHA256_MAC_LEN);
5198 		test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
5199 		r_hash = test_hash;
5200 	}
5201 #endif /* CONFIG_TESTING_OPTIONS */
5202 
5203 	/* Responder Bootstrapping Key Hash */
5204 	dpp_build_attr_r_bootstrap_key_hash(msg, r_hash);
5205 	wpa_hexdump_buf(MSG_DEBUG,
5206 			"DPP: Push Button Presence Announcement frame attributes",
5207 			msg);
5208 	return msg;
5209 }
5210 
5211 
dpp_build_pb_announcement_resp(struct dpp_bootstrap_info * bi,const u8 * e_hash,const u8 * c_nonce,size_t c_nonce_len)5212 struct wpabuf * dpp_build_pb_announcement_resp(struct dpp_bootstrap_info *bi,
5213 					       const u8 *e_hash,
5214 					       const u8 *c_nonce,
5215 					       size_t c_nonce_len)
5216 {
5217 	struct wpabuf *msg;
5218 	const u8 *i_hash = bi->pubkey_hash_chirp;
5219 #ifdef CONFIG_TESTING_OPTIONS
5220 	u8 test_hash[SHA256_MAC_LEN];
5221 #endif /* CONFIG_TESTING_OPTIONS */
5222 
5223 	wpa_printf(MSG_DEBUG,
5224 		   "DPP: Build Push Button Presence Announcement Response frame");
5225 
5226 	msg = dpp_alloc_msg(DPP_PA_PB_PRESENCE_ANNOUNCEMENT_RESP,
5227 			    2 * (4 + SHA256_MAC_LEN) + 4 + c_nonce_len);
5228 	if (!msg)
5229 		return NULL;
5230 
5231 #ifdef CONFIG_TESTING_OPTIONS
5232 	if (dpp_test == DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_PB_RESP) {
5233 		wpa_printf(MSG_INFO,
5234 			   "DPP: TESTING - invalid I-Bootstrap Key Hash");
5235 		os_memcpy(test_hash, i_hash, SHA256_MAC_LEN);
5236 		test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
5237 		i_hash = test_hash;
5238 	} else if (dpp_test == DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_PB_RESP) {
5239 		wpa_printf(MSG_INFO,
5240 			   "DPP: TESTING - invalid R-Bootstrap Key Hash");
5241 		os_memcpy(test_hash, e_hash, SHA256_MAC_LEN);
5242 		test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
5243 		e_hash = test_hash;
5244 	}
5245 #endif /* CONFIG_TESTING_OPTIONS */
5246 
5247 	/* Initiator Bootstrapping Key Hash */
5248 	wpa_printf(MSG_DEBUG, "DPP: I-Bootstrap Key Hash");
5249 	wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH);
5250 	wpabuf_put_le16(msg, SHA256_MAC_LEN);
5251 	wpabuf_put_data(msg, i_hash, SHA256_MAC_LEN);
5252 
5253 	/* Responder Bootstrapping Key Hash */
5254 	dpp_build_attr_r_bootstrap_key_hash(msg, e_hash);
5255 
5256 	/* Configurator Nonce */
5257 	wpabuf_put_le16(msg, DPP_ATTR_CONFIGURATOR_NONCE);
5258 	wpabuf_put_le16(msg, c_nonce_len);
5259 	wpabuf_put_data(msg, c_nonce, c_nonce_len);
5260 
5261 	wpa_hexdump_buf(MSG_DEBUG,
5262 			"DPP: Push Button Presence Announcement Response frame attributes",
5263 			msg);
5264 	return msg;
5265 }
5266 
5267 #endif /* CONFIG_DPP3 */
5268