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