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