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