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