xref: /wlan-dirver/utils/sigma-dut/dpp.c (revision a745074d5b621f42f13b57bd5219f7fbde9b05c5)
1 /*
2  * Sigma Control API DUT (station/AP/sniffer)
3  * Copyright (c) 2017, Qualcomm Atheros, Inc.
4  * Copyright (c) 2018-2020, The Linux Foundation
5  * All Rights Reserved.
6  * Licensed under the Clear BSD license. See README for more details.
7  */
8 
9 #include "sigma_dut.h"
10 #include <sys/wait.h>
11 #include "wpa_ctrl.h"
12 #include "wpa_helpers.h"
13 
14 extern char *sigma_wpas_ctrl;
15 extern char *sigma_cert_path;
16 
17 #ifdef ANDROID
18 char *dpp_qrcode_file = "/sdcard/wpadebug_qrdata.txt";
19 #endif /* ANDROID */
20 
21 
22 static int sigma_dut_is_ap(struct sigma_dut *dut)
23 {
24 	return dut->device_type == AP_unknown ||
25 		dut->device_type == AP_testbed ||
26 		dut->device_type == AP_dut;
27 }
28 
29 
30 static int dpp_hostapd_run(struct sigma_dut *dut)
31 {
32 	if (dut->hostapd_running)
33 		return 0;
34 
35 	sigma_dut_print(dut, DUT_MSG_INFO,
36 			"Starting hostapd in unconfigured state for DPP");
37 	snprintf(dut->ap_ssid, sizeof(dut->ap_ssid), "unconfigured");
38 	if (!dut->ap_oper_chn)
39 		dut->ap_channel = 11;
40 	dut->ap_is_dual = 0;
41 	dut->ap_mode = dut->ap_channel <= 14 ? AP_11ng : AP_11na;
42 	dut->ap_key_mgmt = AP_OPEN;
43 	dut->ap_cipher = AP_PLAIN;
44 	if (!dut->ap_dpp_conf_addr || !dut->ap_dpp_conf_pkhash)
45 		dut->ap_start_disabled = 1;
46 	return cmd_ap_config_commit(dut, NULL, NULL) == 1 ? 0 : -1;
47 }
48 
49 
50 static int dpp_hostapd_beacon(struct sigma_dut *dut)
51 {
52 	const char *ifname = dut->hostapd_ifname;
53 
54 	if (!dut->ap_start_disabled)
55 		return 0;
56 
57 	sigma_dut_print(dut, DUT_MSG_INFO, "Start beaconing");
58 	if (!ifname ||
59 	    wpa_command(ifname, "SET start_disabled 0") < 0 ||
60 	    wpa_command(ifname, "DISABLE") < 0 ||
61 	    wpa_command(ifname, "ENABLE") < 0)
62 		return -1;
63 
64 	dut->ap_start_disabled = 0;
65 	return 0;
66 }
67 
68 
69 static const char * dpp_get_curve(struct sigma_cmd *cmd, const char *arg)
70 {
71 	const char *val = get_param(cmd, arg);
72 
73 	if (!val)
74 		val = "P-256";
75 	else if (strcasecmp(val, "BP-256R1") == 0)
76 		val = "BP-256";
77 	else if (strcasecmp(val, "BP-384R1") == 0)
78 		val = "BP-384";
79 	else if (strcasecmp(val, "BP-512R1") == 0)
80 		val = "BP-512";
81 
82 	return val;
83 }
84 
85 
86 static enum sigma_cmd_result
87 dpp_get_local_bootstrap(struct sigma_dut *dut, struct sigma_conn *conn,
88 			struct sigma_cmd *cmd, int send_result, int *success)
89 {
90 	const char *curve = dpp_get_curve(cmd, "DPPCryptoIdentifier");
91 	const char *bs = get_param(cmd, "DPPBS");
92 	const char *chan_list = get_param(cmd, "DPPChannelList");
93 	char *pos, mac[50], buf[200], resp[1000], hex[2000];
94 	const char *ifname = get_station_ifname(dut);
95 	int res;
96 	const char *type;
97 
98 	if (success)
99 		*success = 0;
100 	if (strcasecmp(bs, "QR") == 0) {
101 		type = "qrcode";
102 	} else if (strcasecmp(bs, "NFC") == 0) {
103 		type ="nfc-uri";
104 	} else {
105 		send_resp(dut, conn, SIGMA_ERROR,
106 			  "errorCode,Unsupported DPPBS");
107 		return STATUS_SENT_ERROR;
108 	}
109 
110 	if (sigma_dut_is_ap(dut)) {
111 		u8 bssid[ETH_ALEN];
112 
113 		if (!dut->hostapd_ifname) {
114 			sigma_dut_print(dut, DUT_MSG_ERROR,
115 					"hostapd ifname not specified (-j)");
116 			return ERROR_SEND_STATUS;
117 		}
118 		ifname = dut->hostapd_ifname;
119 		if (get_hwaddr(dut->hostapd_ifname, bssid) < 0) {
120 			sigma_dut_print(dut, DUT_MSG_ERROR,
121 					"Could not get MAC address for %s",
122 					dut->hostapd_ifname);
123 			return ERROR_SEND_STATUS;
124 		}
125 		snprintf(mac, sizeof(mac), "%02x%02x%02x%02x%02x%02x",
126 			 bssid[0], bssid[1], bssid[2],
127 			 bssid[3], bssid[4], bssid[5]);
128 	} else {
129 		if (get_wpa_status(ifname, "address", mac, sizeof(mac)) < 0) {
130 			send_resp(dut, conn, SIGMA_ERROR,
131 				  "errorCode,Failed to get own MAC address from wpa_supplicant");
132 			return STATUS_SENT_ERROR;
133 		}
134 	}
135 
136 	pos = mac;
137 	while (*pos) {
138 		if (*pos == ':')
139 			memmove(pos, pos + 1, strlen(pos));
140 		else
141 			pos++;
142 	}
143 
144 	if (sigma_dut_is_ap(dut) && dpp_hostapd_run(dut) < 0) {
145 		send_resp(dut, conn, SIGMA_ERROR,
146 			  "errorCode,Failed to start hostapd");
147 		return STATUS_SENT_ERROR;
148 	}
149 
150 	if (chan_list &&
151 	    (strcmp(chan_list, "0/0") == 0 || chan_list[0] == '\0')) {
152 		/* No channel list */
153 		res = snprintf(buf, sizeof(buf),
154 			       "DPP_BOOTSTRAP_GEN type=%s curve=%s mac=%s",
155 			       type, curve, mac);
156 	} else if (chan_list) {
157 		/* Channel list override (CTT case) - space separated tuple(s)
158 		 * of OperatingClass/Channel; convert to wpa_supplicant/hostapd
159 		 * format: comma separated tuples */
160 		strlcpy(resp, chan_list, sizeof(resp));
161 		for (pos = resp; *pos; pos++) {
162 			if (*pos == ' ')
163 				*pos = ',';
164 		}
165 		res = snprintf(buf, sizeof(buf),
166 			       "DPP_BOOTSTRAP_GEN type=%s curve=%s chan=%s mac=%s",
167 			       type, curve, resp, mac);
168 	} else {
169 		int channel = 11;
170 
171 		/* Default channel list (normal DUT case) */
172 		if (sigma_dut_is_ap(dut) && dut->hostapd_running &&
173 		    dut->ap_oper_chn &&
174 		    dut->ap_channel > 0 && dut->ap_channel <= 13)
175 			channel = dut->ap_channel;
176 		res = snprintf(buf, sizeof(buf),
177 			       "DPP_BOOTSTRAP_GEN type=%s curve=%s chan=81/%d mac=%s",
178 			       type, curve, channel, mac);
179 	}
180 
181 	if (res < 0 || res >= sizeof(buf) ||
182 	    wpa_command_resp(ifname, buf, resp, sizeof(resp)) < 0 ||
183 	    strncmp(resp, "FAIL", 4) == 0)
184 		return ERROR_SEND_STATUS;
185 	dut->dpp_local_bootstrap = atoi(resp);
186 	snprintf(buf, sizeof(buf), "DPP_BOOTSTRAP_GET_URI %d",
187 		 atoi(resp));
188 	if (wpa_command_resp(ifname, buf, resp, sizeof(resp)) < 0 ||
189 	    strncmp(resp, "FAIL", 4) == 0)
190 		return ERROR_SEND_STATUS;
191 
192 	sigma_dut_print(dut, DUT_MSG_DEBUG, "URI: %s", resp);
193 
194 	if (send_result) {
195 		ascii2hexstr(resp, hex);
196 		res = snprintf(resp, sizeof(resp), "BootstrappingData,%s", hex);
197 		send_resp(dut, conn, SIGMA_COMPLETE,
198 			  res >= 0 && res < sizeof(resp) ? resp : NULL);
199 	}
200 
201 	if (success)
202 		*success = 1;
203 	return STATUS_SENT;
204 }
205 
206 
207 static enum sigma_cmd_result dpp_set_peer_bootstrap(struct sigma_dut *dut,
208 						    struct sigma_conn *conn,
209 						    struct sigma_cmd *cmd)
210 {
211 	const char *val = get_param(cmd, "DPPBootstrappingdata");
212 	char uri[1000];
213 	int res;
214 
215 	if (!val) {
216 		send_resp(dut, conn, SIGMA_ERROR,
217 			  "errorCode,Missing DPPBootstrappingdata");
218 		return STATUS_SENT_ERROR;
219 	}
220 
221 	res = parse_hexstr(val, (unsigned char *) uri, sizeof(uri));
222 	if (res < 0 || (size_t) res >= sizeof(uri))
223 		return ERROR_SEND_STATUS;
224 	uri[res] = '\0';
225 	sigma_dut_print(dut, DUT_MSG_DEBUG, "URI: %s", uri);
226 	free(dut->dpp_peer_uri);
227 	dut->dpp_peer_uri = strdup(uri);
228 
229 	return SUCCESS_SEND_STATUS;
230 }
231 
232 
233 static int dpp_hostapd_conf_update(struct sigma_dut *dut,
234 				   struct sigma_conn *conn, const char *ifname,
235 				   struct wpa_ctrl *ctrl)
236 {
237 	int res;
238 	char buf[2000], buf2[2500], *pos, *pos2;
239 	const char *conf_data_events[] = {
240 		"DPP-CONNECTOR",
241 		"DPP-CONFOBJ-PASS",
242 		"DPP-CONFOBJ-PSK",
243 		"DPP-C-SIGN-KEY",
244 		"DPP-NET-ACCESS-KEY",
245 		NULL
246 	};
247 	unsigned int old_timeout;
248 	int legacy_akm, dpp_akm;
249 	char *connector = NULL, *psk = NULL, *csign = NULL,
250 		*net_access_key = NULL;
251 	char pass[64];
252 	int pass_len = 0;
253 	int ret = 0;
254 
255 	sigma_dut_print(dut, DUT_MSG_INFO,
256 			"Update hostapd configuration based on DPP Config Object");
257 
258 	if (wpa_command(ifname, "SET wpa 2") < 0 ||
259 	    wpa_command(ifname, "SET wpa_key_mgmt DPP") < 0 ||
260 	    wpa_command(ifname, "SET ieee80211w 1") < 0 ||
261 	    wpa_command(ifname, "SET rsn_pairwise CCMP") < 0) {
262 		send_resp(dut, conn, SIGMA_ERROR,
263 			  "errorCode,Failed to update AP security parameters");
264 		goto out;
265 	}
266 
267 	res = get_wpa_cli_event(dut, ctrl, "DPP-CONFOBJ-AKM", buf, sizeof(buf));
268 	if (res < 0) {
269 		send_resp(dut, conn, SIGMA_ERROR,
270 			  "errorCode,No DPP-CONFOBJ-AKM");
271 		goto out;
272 	}
273 	pos = strchr(buf, ' ');
274 	if (!pos)
275 		return -2;
276 	pos++;
277 	sigma_dut_print(dut, DUT_MSG_INFO,
278 			"DPP: Config Object AKM: %s", pos);
279 	legacy_akm = strstr(pos, "psk") != NULL || strstr(pos, "sae") != NULL;
280 	dpp_akm = strstr(pos, "dpp") != NULL;
281 
282 	res = get_wpa_cli_event(dut, ctrl, "DPP-CONFOBJ-SSID",
283 				buf, sizeof(buf));
284 	if (res < 0) {
285 		send_resp(dut, conn, SIGMA_ERROR,
286 			  "errorCode,No DPP-CONFOBJ-SSID");
287 		goto out;
288 	}
289 	pos = strchr(buf, ' ');
290 	if (!pos)
291 		return -2;
292 	pos++;
293 	sigma_dut_print(dut, DUT_MSG_INFO,
294 			"DPP: Config Object SSID: %s", pos);
295 	snprintf(buf2, sizeof(buf2), "SET ssid %s", pos);
296 	if (wpa_command(ifname, buf2) < 0) {
297 		send_resp(dut, conn, SIGMA_ERROR,
298 			  "errorCode,Failed to update AP SSID");
299 		goto out;
300 	}
301 
302 	if (wpa_command(ifname, "SET utf8_ssid 1") < 0) {
303 		send_resp(dut, conn, SIGMA_ERROR,
304 			  "errorCode,Failed to update AP UTF-8 SSID capa");
305 		goto out;
306 	}
307 
308 	while ((dpp_akm && (!connector || !csign || !net_access_key)) ||
309 	       (legacy_akm && !pass_len && !psk)) {
310 		res = get_wpa_cli_events(dut, ctrl, conf_data_events,
311 					 buf, sizeof(buf));
312 		if (res < 0) {
313 			send_resp(dut, conn, SIGMA_ERROR,
314 				  "errorCode,Not all config object information received");
315 			goto out;
316 		}
317 
318 		if (strstr(buf, "DPP-CONNECTOR")) {
319 			pos = strchr(buf, ' ');
320 			if (!pos) {
321 				ret = -2;
322 				goto out;
323 			}
324 			pos++;
325 			sigma_dut_print(dut, DUT_MSG_INFO, "DPP: Connector: %s",
326 					pos);
327 			if (!connector)
328 				connector = strdup(pos);
329 		} else if (strstr(buf, "DPP-C-SIGN-KEY")) {
330 			pos = strchr(buf, ' ');
331 			if (!pos) {
332 				ret = -2;
333 				goto out;
334 			}
335 			pos++;
336 			sigma_dut_print(dut, DUT_MSG_INFO,
337 					"DPP: C-sign-key: %s", pos);
338 			if (!csign)
339 				csign = strdup(pos);
340 		} else if (strstr(buf, "DPP-NET-ACCESS-KEY")) {
341 			pos = strchr(buf, ' ');
342 			if (!pos) {
343 				ret = -2;
344 				goto out;
345 			}
346 			pos++;
347 			if (!net_access_key)
348 				net_access_key = strdup(pos);
349 		} else if (strstr(buf, "DPP-CONFOBJ-PASS")) {
350 			pos = strchr(buf, ' ');
351 			if (!pos) {
352 				ret = -2;
353 				goto out;
354 			}
355 			pos++;
356 			pass_len = parse_hexstr(pos, (u8 *) pass, sizeof(pass));
357 			if (pass_len < 0 || (size_t) pass_len >= sizeof(pass)) {
358 				ret = -2;
359 				goto out;
360 			}
361 			pass[pass_len] = '\0';
362 			sigma_dut_print(dut, DUT_MSG_INFO,
363 					"DPP: Passphrase: %s", pass);
364 		} else if (strstr(buf, "DPP-CONFOBJ-PSK")) {
365 			pos = strchr(buf, ' ');
366 			if (!pos) {
367 				ret = -2;
368 				goto out;
369 			}
370 			pos++;
371 			sigma_dut_print(dut, DUT_MSG_INFO, "DPP: PSK: %s", pos);
372 			if (!psk)
373 				psk = strdup(pos);
374 		}
375 	}
376 
377 	if ((!connector || !dpp_akm) &&
378 	    wpa_command(ifname, "SET wpa_key_mgmt WPA-PSK") < 0) {
379 		send_resp(dut, conn, SIGMA_ERROR,
380 			  "errorCode,Failed to update AP security parameters");
381 		goto out;
382 	}
383 
384 	if (connector && dpp_akm && legacy_akm &&
385 	    wpa_command(ifname, "SET wpa_key_mgmt DPP WPA-PSK") < 0) {
386 		send_resp(dut, conn, SIGMA_ERROR,
387 			  "errorCode,Failed to update AP security parameters");
388 		goto out;
389 	}
390 
391 	if (pass_len) {
392 		snprintf(buf2, sizeof(buf2), "SET wpa_passphrase %s",
393 			 pass);
394 		if (wpa_command(ifname, buf2) < 0) {
395 			send_resp(dut, conn, SIGMA_ERROR,
396 				  "errorCode,Failed to set passphrase");
397 			goto out;
398 		}
399 	} else if (psk) {
400 		snprintf(buf2, sizeof(buf2), "SET wpa_psk %s", psk);
401 		if (wpa_command(ifname, buf2) < 0) {
402 			send_resp(dut, conn, SIGMA_ERROR,
403 				  "errorCode,Failed to set PSK");
404 			goto out;
405 		}
406 	}
407 
408 	if (connector) {
409 		snprintf(buf2, sizeof(buf2), "SET dpp_connector %s", connector);
410 		if (wpa_command(ifname, buf2) < 0) {
411 			send_resp(dut, conn, SIGMA_ERROR,
412 				  "errorCode,Failed to update AP Connector");
413 			goto out;
414 		}
415 	}
416 
417 	if (csign) {
418 		snprintf(buf2, sizeof(buf2), "SET dpp_csign %s", csign);
419 		if (wpa_command(ifname, buf2) < 0) {
420 			send_resp(dut, conn, SIGMA_ERROR,
421 				  "errorCode,Failed to update AP C-sign-key");
422 			goto out;
423 		}
424 	}
425 
426 	if (net_access_key) {
427 		pos2 = strchr(net_access_key, ' ');
428 		if (pos2)
429 			*pos2++ = '\0';
430 		sigma_dut_print(dut, DUT_MSG_INFO, "DPP: netAccessKey: %s",
431 				net_access_key);
432 		snprintf(buf2, sizeof(buf2), "SET dpp_netaccesskey %s",
433 			 net_access_key);
434 		if (wpa_command(ifname, buf2) < 0) {
435 			send_resp(dut, conn, SIGMA_ERROR,
436 				  "errorCode,Failed to update AP netAccessKey");
437 			goto out;
438 		}
439 		if (pos2) {
440 			sigma_dut_print(dut, DUT_MSG_INFO,
441 					"DPP: netAccessKey expiry: %s", pos2);
442 			snprintf(buf2, sizeof(buf2),
443 				 "SET dpp_netaccesskey_expiry %s", pos2);
444 			if (wpa_command(ifname, buf2) < 0) {
445 				send_resp(dut, conn, SIGMA_ERROR,
446 					  "errorCode,Failed to update AP netAccessKey expiry");
447 				goto out;
448 			}
449 		}
450 	}
451 
452 	if (dut->ap_start_disabled)
453 		sigma_dut_print(dut, DUT_MSG_INFO, "Clear ap_start_disabled");
454 	if (wpa_command(ifname, "SET start_disabled 0") < 0 &&
455 	    dut->ap_start_disabled) {
456 		send_resp(dut, conn, SIGMA_ERROR,
457 			  "errorCode,Failed to update AP security parameters");
458 		goto out;
459 	}
460 	dut->ap_start_disabled = 0;
461 
462 	/* Wait for a possible Configuration Result to be sent */
463 	old_timeout = dut->default_timeout;
464 	dut->default_timeout = 1;
465 	get_wpa_cli_event(dut, ctrl, "DPP-TX-STATUS", buf, sizeof(buf));
466 	dut->default_timeout = old_timeout;
467 
468 	if (dut->ap_oper_chn) {
469 		sigma_dut_print(dut, DUT_MSG_INFO,
470 				"Set AP operating channel %d",
471 				dut->ap_channel);
472 		snprintf(buf, sizeof(buf), "SET channel %d", dut->ap_channel);
473 		wpa_command(ifname, buf);
474 	}
475 	if (wpa_command(ifname, "DISABLE") < 0 ||
476 	    wpa_command(ifname, "ENABLE") < 0) {
477 		send_resp(dut, conn, SIGMA_ERROR,
478 			  "errorCode,Failed to update AP configuration");
479 		goto out;
480 	}
481 
482 	res = get_wpa_cli_event(dut, ctrl, "AP-ENABLED", buf, sizeof(buf));
483 	if (res < 0) {
484 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,No AP-ENABLED");
485 		goto out;
486 	}
487 
488 	ret = 1;
489 out:
490 	free(connector);
491 	free(psk);
492 	free(csign);
493 	free(net_access_key);
494 	return ret;
495 }
496 
497 
498 struct dpp_test_info {
499 	const char *step;
500 	const char *frame;
501 	const char *attr;
502 	int value;
503 };
504 
505 static const struct dpp_test_info dpp_tests[] = {
506 	{ "InvalidValue", "AuthenticationRequest", "WrappedData", 1 },
507 	{ "InvalidValue", "AuthenticationResponse", "WrappedData", 2 },
508 	{ "InvalidValue", "AuthenticationResponse", "PrimaryWrappedData", 2 },
509 	{ "InvalidValue", "AuthenticationConfirm", "WrappedData", 3 },
510 	{ "InvalidValue", "PKEXCRRequest", "WrappedData", 4 },
511 	{ "InvalidValue", "PKEXCRResponse", "WrappedData", 5 },
512 	{ "InvalidValue", "ConfigurationRequest", "WrappedData", 6 },
513 	{ "InvalidValue", "ConfigurationResponse", "WrappedData", 7 },
514 	{ "InvalidValue", "AuthenticationRequest", "InitCapabilities", 8 },
515 	{ "MissingAttribute", "AuthenticationRequest", "RespBSKeyHash", 10 },
516 	{ "MissingAttribute", "AuthenticationRequest", "InitBSKeyHash", 11 },
517 	{ "MissingAttribute", "AuthenticationRequest", "InitProtocolKey", 12 },
518 	{ "MissingAttribute", "AuthenticationRequest", "InitNonce", 13 },
519 	{ "MissingAttribute", "AuthenticationRequest", "InitCapabilities", 14 },
520 	{ "MissingAttribute", "AuthenticationRequest", "WrappedData", 15 },
521 	{ "MissingAttribute", "AuthenticationResponse", "DPPStatus", 16 },
522 	{ "MissingAttribute", "AuthenticationResponse", "RespBSKeyHash", 17 },
523 	{ "MissingAttribute", "AuthenticationResponse", "InitBSKeyHash", 18 },
524 	{ "MissingAttribute", "AuthenticationResponse", "RespProtocolKey", 19 },
525 	{ "MissingAttribute", "AuthenticationResponse", "RespNonce", 20 },
526 	{ "MissingAttribute", "AuthenticationResponse", "InitNonce", 21 },
527 	{ "MissingAttribute", "AuthenticationResponse", "RespCapabilities",
528 	  22 },
529 	{ "MissingAttribute", "AuthenticationResponse", "RespAuthTag", 23 },
530 	{ "MissingAttribute", "AuthenticationResponse", "WrappedData", 24 },
531 	{ "MissingAttribute", "AuthenticationResponse", "PrimaryWrappedData",
532 	  24 },
533 	{ "MissingAttribute", "AuthenticationConfirm", "DPPStatus", 25 },
534 	{ "MissingAttribute", "AuthenticationConfirm", "RespBSKeyHash", 26 },
535 	{ "MissingAttribute", "AuthenticationConfirm", "InitBSKeyHash", 27 },
536 	{ "MissingAttribute", "AuthenticationConfirm", "InitAuthTag", 28 },
537 	{ "MissingAttribute", "AuthenticationConfirm", "WrappedData", 29 },
538 	{ "InvalidValue", "AuthenticationResponse", "InitNonce", 30 },
539 	{ "InvalidValue", "AuthenticationResponse", "RespCapabilities", 31 },
540 	{ "InvalidValue", "AuthenticationResponse", "RespAuthTag", 32 },
541 	{ "InvalidValue", "AuthenticationConfirm", "InitAuthTag", 33 },
542 	{ "MissingAttribute", "PKEXExchangeRequest", "FiniteCyclicGroup", 34 },
543 	{ "MissingAttribute", "PKEXExchangeRequest", "EncryptedKey", 35 },
544 	{ "MissingAttribute", "PKEXExchangeResponse", "DPPStatus", 36 },
545 	{ "MissingAttribute", "PKEXExchangeResponse", "EncryptedKey", 37 },
546 	{ "MissingAttribute", "PKEXCRRequest", "BSKey", 38 },
547 	{ "MissingAttribute", "PKEXCRRequest", "InitAuthTag", 39 },
548 	{ "MissingAttribute", "PKEXCRRequest", "WrappedData", 40 },
549 	{ "MissingAttribute", "PKEXCRResponse", "BSKey", 41 },
550 	{ "MissingAttribute", "PKEXCRResponse", "RespAuthTag", 42 },
551 	{ "MissingAttribute", "PKEXCRResponse", "WrappedData", 43 },
552 	{ "InvalidValue", "PKEXExchangeRequest", "EncryptedKey", 44 },
553 	{ "InvalidValue", "PKEXExchangeResponse", "EncryptedKey", 45 },
554 	{ "InvalidValue", "PKEXExchangeResponse", "DPPStatus", 46 },
555 	{ "InvalidValue", "PKEXCRRequest", "BSKey", 47 },
556 	{ "InvalidValue", "PKEXCRResponse", "BSKey", 48 },
557 	{ "InvalidValue", "PKEXCRRequest", "InitAuthTag", 49 },
558 	{ "InvalidValue", "PKEXCRResponse", "RespAuthTag", 50 },
559 	{ "MissingAttribute", "ConfigurationRequest", "EnrolleeNonce", 51 },
560 	{ "MissingAttribute", "ConfigurationRequest", "ConfigAttr", 52 },
561 	{ "MissingAttribute", "ConfigurationRequest", "WrappedData", 53 },
562 	{ "MissingAttribute", "ConfigurationResponse", "EnrolleeNonce", 54 },
563 	{ "MissingAttribute", "ConfigurationResponse", "ConfigObj", 55 },
564 	{ "MissingAttribute", "ConfigurationResponse", "DPPStatus", 56 },
565 	{ "MissingAttribute", "ConfigurationResponse", "WrappedData", 57 },
566 	{ "InvalidValue", "ConfigurationResponse", "DPPStatus", 58 },
567 	{ "InvalidValue", "ConfigurationResponse", "EnrolleeNonce", 59 },
568 	{ "MissingAttribute", "PeerDiscoveryRequest", "TransactionID", 60 },
569 	{ "MissingAttribute", "PeerDiscoveryRequest", "Connector", 61 },
570 	{ "MissingAttribute", "PeerDiscoveryResponse", "TransactionID", 62 },
571 	{ "MissingAttribute", "PeerDiscoveryResponse", "DPPStatus", 63 },
572 	{ "MissingAttribute", "PeerDiscoveryResponse", "Connector", 64 },
573 	{ "InvalidValue", "AuthenticationRequest", "InitProtocolKey", 66 },
574 	{ "InvalidValue", "AuthenticationResponse", "RespProtocolKey", 67 },
575 	{ "InvalidValue", "AuthenticationRequest", "RespBSKeyHash", 68 },
576 	{ "InvalidValue", "AuthenticationRequest", "InitBSKeyHash", 69 },
577 	{ "InvalidValue", "AuthenticationResponse", "RespBSKeyHash", 70 },
578 	{ "InvalidValue", "AuthenticationResponse", "InitBSKeyHash", 71 },
579 	{ "InvalidValue", "AuthenticationConfirm", "RespBSKeyHash", 72 },
580 	{ "InvalidValue", "AuthenticationConfirm", "InitBSKeyHash", 73 },
581 	{ "InvalidValue", "AuthenticationResponse", "DPPStatus", 74 },
582 	{ "InvalidValue", "AuthenticationConfirm", "DPPStatus", 75 },
583 	{ "InvalidValue", "ConfigurationRequest", "ConfigAttr", 76 },
584 	{ "InvalidValue", "PeerDiscoveryResponse", "TransactionID", 77 },
585 	{ "InvalidValue", "PeerDiscoveryResponse", "DPPStatus", 78 },
586 	{ "InvalidValue", "PeerDiscoveryResponse", "Connector", 79 },
587 	{ "InvalidValue", "PeerDiscoveryRequest", "Connector", 80 },
588 	{ "InvalidValue", "AuthenticationRequest", "InitNonce", 81 },
589 	{ "InvalidValue", "PeerDiscoveryRequest", "TransactionID", 82 },
590 	{ "InvalidValue", "ConfigurationRequest", "EnrolleeNonce", 83 },
591 	{ "Timeout", "PKEXExchangeResponse", NULL, 84 },
592 	{ "Timeout", "PKEXCRRequest", NULL, 85 },
593 	{ "Timeout", "PKEXCRResponse", NULL, 86 },
594 	{ "Timeout", "AuthenticationRequest", NULL, 87 },
595 	{ "Timeout", "AuthenticationResponse", NULL, 88 },
596 	{ "Timeout", "AuthenticationConfirm", NULL, 89 },
597 	{ "Timeout", "ConfigurationRequest", NULL, 90 },
598 	{ NULL, NULL, NULL, 0 }
599 };
600 
601 
602 static int dpp_get_test(const char *step, const char *frame, const char *attr)
603 {
604 	int i;
605 
606 	for (i = 0; dpp_tests[i].step; i++) {
607 		if (strcasecmp(step, dpp_tests[i].step) == 0 &&
608 		    strcasecmp(frame, dpp_tests[i].frame) == 0 &&
609 		    ((!attr && dpp_tests[i].attr == NULL) ||
610 		     (attr && strcasecmp(attr, dpp_tests[i].attr) == 0)))
611 			return dpp_tests[i].value;
612 	}
613 
614 	return -1;
615 }
616 
617 
618 static int dpp_wait_tx(struct sigma_dut *dut, struct wpa_ctrl *ctrl,
619 		       int frame_type)
620 {
621 	char buf[200], tmp[20];
622 	int res;
623 
624 	snprintf(tmp, sizeof(tmp), "type=%d", frame_type);
625 	for (;;) {
626 		res = get_wpa_cli_event(dut, ctrl, "DPP-TX", buf, sizeof(buf));
627 		if (res < 0)
628 			return -1;
629 		if (strstr(buf, tmp) != NULL)
630 			break;
631 	}
632 
633 	return 0;
634 }
635 
636 
637 static int dpp_wait_tx_status(struct sigma_dut *dut, struct wpa_ctrl *ctrl,
638 			      int frame_type)
639 {
640 	char buf[200], tmp[20];
641 	int res;
642 
643 	snprintf(tmp, sizeof(tmp), "type=%d", frame_type);
644 	for (;;) {
645 		res = get_wpa_cli_event(dut, ctrl, "DPP-TX", buf, sizeof(buf));
646 		if (res < 0)
647 			return -1;
648 		if (strstr(buf, tmp) != NULL)
649 			break;
650 	}
651 
652 	res = get_wpa_cli_event(dut, ctrl, "DPP-TX-STATUS",
653 				buf, sizeof(buf));
654 	if (res < 0 || strstr(buf, "result=FAILED") != NULL)
655 		return -1;
656 
657 	return 0;
658 }
659 
660 
661 static int dpp_wait_rx(struct sigma_dut *dut, struct wpa_ctrl *ctrl,
662 		       int frame_type, unsigned int max_wait)
663 {
664 	char buf[200], tmp[20];
665 	int res;
666 	unsigned int old_timeout;
667 
668 	old_timeout = dut->default_timeout;
669 	if (max_wait > 0 && dut->default_timeout > max_wait)
670 		dut->default_timeout = max_wait;
671 
672 	snprintf(tmp, sizeof(tmp), "type=%d", frame_type);
673 	for (;;) {
674 		res = get_wpa_cli_event(dut, ctrl, "DPP-RX", buf, sizeof(buf));
675 		if (res < 0) {
676 			dut->default_timeout = old_timeout;
677 			return -1;
678 		}
679 		if (strstr(buf, tmp) != NULL)
680 			break;
681 	}
682 
683 	dut->default_timeout = old_timeout;
684 	return 0;
685 }
686 
687 
688 static int dpp_wait_rx_conf_req(struct sigma_dut *dut, struct wpa_ctrl *ctrl,
689 				unsigned int max_wait)
690 {
691 	char buf[200];
692 	int res;
693 	unsigned int old_timeout;
694 
695 	old_timeout = dut->default_timeout;
696 	if (max_wait > 0 && dut->default_timeout > max_wait)
697 		dut->default_timeout = max_wait;
698 
699 	for (;;) {
700 		res = get_wpa_cli_event(dut, ctrl, "DPP-CONF-REQ-RX",
701 					buf, sizeof(buf));
702 		if (res < 0) {
703 			dut->default_timeout = old_timeout;
704 			return -1;
705 		}
706 
707 		break;
708 	}
709 
710 	dut->default_timeout = old_timeout;
711 	return 0;
712 }
713 
714 
715 static int dpp_scan_peer_qrcode(struct sigma_dut *dut)
716 {
717 #ifdef ANDROID
718 	char buf[100];
719 	char *buf2 = NULL;
720 	FILE *fp = NULL;
721 	uint32_t length;
722 	unsigned int count;
723 
724 	unlink(dpp_qrcode_file);
725 
726 	snprintf(buf, sizeof(buf),
727 		 "am start -n w1.fi.wpadebug/w1.fi.wpadebug.QrCodeReadActivity");
728 	if (system(buf) != 0) {
729 		sigma_dut_print(dut, DUT_MSG_ERROR,
730 				"Failed to launch QR Code scanner");
731 		return -1;
732 	}
733 
734 	count = 0;
735 	while (!(fp = fopen(dpp_qrcode_file, "r"))) {
736 		if (count > dut->default_timeout) {
737 			sigma_dut_print(dut, DUT_MSG_ERROR,
738 					"Failed to open dpp_qrcode_file - QR Code scanning timed out");
739 			return -1;
740 		}
741 
742 		sleep(1);
743 		count++;
744 	}
745 
746 	if (fseek(fp, 0, SEEK_END) < 0 || (length = ftell(fp)) <= 0 ||
747 	    fseek(fp, 0, SEEK_SET) < 0) {
748 		sigma_dut_print(dut, DUT_MSG_ERROR,
749 				"Failed to get QR Code result file length");
750 		fclose(fp);
751 		return -1;
752 	}
753 
754 	buf2 = malloc(length + 1);
755 	if (!buf2) {
756 		fclose(fp);
757 		return -1;
758 	}
759 
760 	if (fread(buf2, 1, length, fp) != length) {
761 		fclose(fp);
762 		free(buf2);
763 		return -1;
764 	}
765 
766 	fclose(fp);
767 	buf2[length] = '\0';
768 
769 	free(dut->dpp_peer_uri);
770 	dut->dpp_peer_uri = strdup(buf2);
771 	free(buf2);
772 	return 0;
773 #else /* ANDROID */
774 	pid_t pid;
775 	int pid_status;
776 	int pipe_out[2];
777 	char buf[4000], *pos;
778 	ssize_t len;
779 	int res = -1, ret;
780 	struct timeval tv;
781 	fd_set rfd;
782 
783 	if (pipe(pipe_out) != 0) {
784 		perror("pipe");
785 		return -1;
786 	}
787 
788 	pid = fork();
789 	if (pid < 0) {
790 		perror("fork");
791 		close(pipe_out[0]);
792 		close(pipe_out[1]);
793 		return -1;
794 	}
795 
796 	if (pid == 0) {
797 		char *argv[4] = { "zbarcam", "--raw", "--prescale=320x240",
798 				  NULL };
799 
800 		dup2(pipe_out[1], STDOUT_FILENO);
801 		close(pipe_out[0]);
802 		close(pipe_out[1]);
803 		execv("/usr/bin/zbarcam", argv);
804 		perror("execv");
805 		exit(0);
806 		return -1;
807 	}
808 
809 	close(pipe_out[1]);
810 
811 	FD_ZERO(&rfd);
812 	FD_SET(pipe_out[0], &rfd);
813 	tv.tv_sec = dut->default_timeout;
814 	tv.tv_usec = 0;
815 
816 	ret = select(pipe_out[0] + 1, &rfd, NULL, NULL, &tv);
817 	if (ret < 0) {
818 		perror("select");
819 		goto out;
820 	}
821 	if (ret == 0) {
822 		sigma_dut_print(dut, DUT_MSG_DEBUG,
823 				"QR Code scanning timed out");
824 		goto out;
825 	}
826 
827 	len = read(pipe_out[0], buf, sizeof(buf));
828 	if (len <= 0)
829 		goto out;
830 	if (len == sizeof(buf))
831 		len--;
832 	buf[len] = '\0';
833 	pos = strchr(buf, '\n');
834 	if (pos)
835 		*pos = '\0';
836 	sigma_dut_print(dut, DUT_MSG_DEBUG, "URI from QR scanner: %s", buf);
837 
838 	free(dut->dpp_peer_uri);
839 	dut->dpp_peer_uri = strdup(buf);
840 	res = 0;
841 out:
842 	close(pipe_out[0]);
843 	kill(pid, SIGTERM);
844 	waitpid(pid, &pid_status, 0);
845 
846 	return res;
847 #endif /* ANDROID */
848 }
849 
850 
851 static int dpp_display_own_qrcode(struct sigma_dut *dut)
852 {
853 	char buf[200], resp[2000];
854 	const char *ifname = get_station_ifname(dut);
855 #ifdef ANDROID
856 	FILE *fp;
857 #else /* ANDROID */
858 	pid_t pid;
859 	int pid_status;
860 #endif /* ANDROID */
861 
862 	snprintf(buf, sizeof(buf), "DPP_BOOTSTRAP_GET_URI %d",
863 		 dut->dpp_local_bootstrap);
864 	if (wpa_command_resp(ifname, buf, resp, sizeof(resp)) < 0 ||
865 	    strncmp(resp, "FAIL", 4) == 0)
866 		return -2;
867 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Own bootstrap URI: %s", resp);
868 
869 #ifdef ANDROID
870 	unlink(dpp_qrcode_file);
871 
872 	fp = fopen(dpp_qrcode_file, "w");
873 	if (!fp) {
874 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open file %s",
875 				dpp_qrcode_file);
876 		return -2;
877 	}
878 
879 	fwrite(resp, 1, strlen(resp), fp);
880 	fclose(fp);
881 
882 	snprintf(buf, sizeof(buf),
883 		 "am start -n w1.fi.wpadebug/w1.fi.wpadebug.QrCodeDisplayActivity");
884 	if (system(buf) != 0) {
885 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to display QR Code");
886 		return -1;
887 	}
888 #else /* ANDROID */
889 	pid = fork();
890 	if (pid < 0) {
891 		perror("fork");
892 		return -1;
893 	}
894 
895 	if (pid == 0) {
896 		char *argv[3] = { "qr", resp, NULL };
897 
898 		execv("/usr/bin/qr", argv);
899 		perror("execv");
900 		exit(0);
901 		return -1;
902 	}
903 
904 	waitpid(pid, &pid_status, 0);
905 #endif /* ANDROID */
906 
907 	return 0;
908 }
909 
910 
911 static int dpp_process_auth_response(struct sigma_dut *dut,
912 				     struct sigma_conn *conn,
913 				     struct wpa_ctrl *ctrl,
914 				     const char **auth_events,
915 				     const char *action_type,
916 				     int check_mutual, char *buf, size_t buflen)
917 {
918 	int res;
919 
920 	res = get_wpa_cli_events(dut, ctrl, auth_events, buf, buflen);
921 	if (res < 0) {
922 		send_resp(dut, conn, SIGMA_COMPLETE,
923 			  "BootstrapResult,OK,AuthResult,Timeout");
924 		return res;
925 	}
926 	sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP auth result: %s", buf);
927 
928 	if (strstr(buf, "DPP-RESPONSE-PENDING")) {
929 		/* Display own QR code in manual mode */
930 		if (action_type && strcasecmp(action_type, "ManualDPP") == 0 &&
931 		    dpp_display_own_qrcode(dut) < 0) {
932 			send_resp(dut, conn, SIGMA_ERROR,
933 				  "errorCode,Failed to display own QR code");
934 			return -1;
935 		}
936 
937 		/* Wait for the actual result after the peer has scanned the
938 		 * QR Code. */
939 		res = get_wpa_cli_events(dut, ctrl, auth_events,
940 					 buf, buflen);
941 		if (res < 0) {
942 			send_resp(dut, conn, SIGMA_COMPLETE,
943 				  "BootstrapResult,OK,AuthResult,Timeout");
944 			return res;
945 		}
946 
947 		sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP auth result: %s", buf);
948 	} else if (strstr(buf, "DPP-AUTH-INIT-FAILED")) {
949 		send_resp(dut, conn, SIGMA_ERROR,
950 			  "errorCode,Peer did not reply to DPP Authentication Request");
951 		return -1;
952 	}
953 
954 	if (check_mutual) {
955 		if (strstr(buf, "DPP-NOT-COMPATIBLE")) {
956 			send_resp(dut, conn, SIGMA_COMPLETE,
957 				  "BootstrapResult,OK,AuthResult,ROLES_NOT_COMPATIBLE");
958 			return -1;
959 		}
960 
961 		if (!strstr(buf, "DPP-AUTH-DIRECTION")) {
962 			send_resp(dut, conn, SIGMA_ERROR,
963 				  "errorCode,No event for auth direction seen");
964 			return -1;
965 		}
966 
967 		sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP auth direction: %s",
968 				buf);
969 		if (strstr(buf, "mutual=1") == NULL) {
970 			send_resp(dut, conn, SIGMA_ERROR,
971 				  "errorCode,Peer did not use mutual authentication");
972 			return -1;
973 		}
974 	}
975 
976 	return 0;
977 }
978 
979 
980 static int dpp_process_csr(struct sigma_dut *dut, const char *ifname,
981 			   char *csr_event)
982 {
983 	FILE *f;
984 	char buf[2000], cmd[2500], tmp[300];
985 	char *pos;
986 	int peer;
987 	size_t len;
988 
989 	pos = strstr(csr_event, " peer=");
990 	if (!pos) {
991 		sigma_dut_print(dut, DUT_MSG_INFO, "No peer id known for CSR");
992 		return -1;
993 	}
994 	pos += 6;
995 	peer = atoi(pos);
996 
997 	pos = strstr(csr_event, " csr=");
998 	if (!pos) {
999 		sigma_dut_print(dut, DUT_MSG_INFO, "No CSR found");
1000 		return -1;
1001 	}
1002 	pos += 5;
1003 
1004 	snprintf(tmp, sizeof(tmp), "%s/dpp-ca-certbag", sigma_cert_path);
1005 	unlink(tmp);
1006 
1007 	snprintf(tmp, sizeof(tmp), "%s/dpp-ca-csr", sigma_cert_path);
1008 	f = fopen(tmp, "w");
1009 	if (!f) {
1010 		sigma_dut_print(dut, DUT_MSG_INFO, "Failed to write CSR file");
1011 		return -1;
1012 	}
1013 	fprintf(f, "%s", pos);
1014 	fclose(f);
1015 
1016 	if (run_system_wrapper(dut, "./dpp-ca.py %s", sigma_cert_path) < 0) {
1017 		sigma_dut_print(dut, DUT_MSG_INFO, "Failed to run dpp-ca.py");
1018 		return -1;
1019 	}
1020 
1021 	snprintf(tmp, sizeof(tmp), "%s/dpp-ca-certbag", sigma_cert_path);
1022 	f = fopen(tmp, "r");
1023 	if (!f) {
1024 		sigma_dut_print(dut, DUT_MSG_INFO, "No certBag available");
1025 		return -1;
1026 	}
1027 	len = fread(buf, 1, sizeof(buf), f);
1028 	fclose(f);
1029 	if (len >= sizeof(buf)) {
1030 		sigma_dut_print(dut, DUT_MSG_INFO, "No bufferroom for certBag");
1031 		return -1;
1032 	}
1033 	buf[len] = '\0';
1034 
1035 	snprintf(cmd, sizeof(cmd), "DPP_CA_SET peer=%d name=certBag value=%s",
1036 		 peer, buf);
1037 	if (wpa_command(ifname, cmd) < 0) {
1038 		sigma_dut_print(dut, DUT_MSG_INFO, "DPP_CA_SET failed");
1039 		return -1;
1040 	}
1041 
1042 	return 0;
1043 }
1044 
1045 
1046 static enum sigma_cmd_result dpp_automatic_dpp(struct sigma_dut *dut,
1047 					       struct sigma_conn *conn,
1048 					       struct sigma_cmd *cmd)
1049 {
1050 	const char *bs = get_param(cmd, "DPPBS");
1051 	const char *type = get_param(cmd, "DPPActionType");
1052 	const char *auth_role = get_param(cmd, "DPPAuthRole");
1053 	const char *prov_role = get_param(cmd, "DPPProvisioningRole");
1054 	const char *pkex_code = get_param(cmd, "DPPPKEXCode");
1055 	const char *pkex_code_id = get_param(cmd, "DPPPKEXCodeIdentifier");
1056 	const char *wait_conn = get_param(cmd, "DPPWaitForConnect");
1057 	const char *self_conf = get_param(cmd, "DPPSelfConfigure");
1058 	const char *step = get_param(cmd, "DPPStep");
1059 	const char *frametype = get_param(cmd, "DPPFrameType");
1060 	const char *attr = get_param(cmd, "DPPIEAttribute");
1061 	const char *action_type = get_param(cmd, "DPPActionType");
1062 	const char *tcp = get_param(cmd, "DPPOverTCP");
1063 	const char *nfc_handover = get_param(cmd, "DPPNFCHandover");
1064 	const char *role;
1065 	const char *netrole = NULL;
1066 	const char *val;
1067 	const char *conf_role;
1068 	int conf_index = -1;
1069 	char buf[2000], *pos, *pos2;
1070 	char buf2[200];
1071 	char conf_ssid[100];
1072 	char conf_pass[100];
1073 	char csrattrs[200];
1074 	char pkex_identifier[200];
1075 	struct wpa_ctrl *ctrl;
1076 	int res;
1077 	unsigned int old_timeout;
1078 	int own_pkex_id = -1;
1079 	const char *ifname = get_station_ifname(dut);
1080 	const char *auth_events[] = {
1081 		"DPP-AUTH-SUCCESS",
1082 		"DPP-AUTH-INIT-FAILED",
1083 		"DPP-NOT-COMPATIBLE",
1084 		"DPP-RESPONSE-PENDING",
1085 		"DPP-SCAN-PEER-QR-CODE",
1086 		"DPP-AUTH-DIRECTION",
1087 		NULL
1088 	};
1089 	const char *conf_events[] = {
1090 		"DPP-CONF-RECEIVED",
1091 		"DPP-CONF-SENT",
1092 		"DPP-CONF-FAILED",
1093 		"DPP-MUD-URL",
1094 		NULL
1095 	};
1096 	const char *conn_events[] = {
1097 		"PMKSA-CACHE-ADDED",
1098 		"CTRL-EVENT-CONNECTED",
1099 		NULL
1100 	};
1101 	const char *group_id_str = NULL;
1102 	char group_id[100];
1103 	char conf2[300];
1104 	const char *result;
1105 	int check_mutual = 0;
1106 	int enrollee_ap;
1107 	int enrollee_configurator;
1108 	int force_gas_fragm = 0;
1109 	int not_dpp_akm = 0;
1110 	int akm_use_selector = 0;
1111 	int conn_status;
1112 	int chirp = 0;
1113 	int manual = strcasecmp(type, "ManualDPP") == 0;
1114 	time_t start, now;
1115 	FILE *f;
1116 	char *no_mud_url = "";
1117 	char *mud_url = no_mud_url;
1118 
1119 	time(&start);
1120 
1121 	if (!wait_conn)
1122 		wait_conn = "no";
1123 	if (!self_conf)
1124 		self_conf = "no";
1125 
1126 	if (!prov_role) {
1127 		send_resp(dut, conn, SIGMA_ERROR,
1128 			  "errorCode,Missing DPPProvisioningRole");
1129 		return STATUS_SENT_ERROR;
1130 	}
1131 
1132 	val = get_param(cmd, "DPPConfEnrolleeRole");
1133 	if (val) {
1134 		enrollee_ap = strcasecmp(val, "AP") == 0;
1135 		enrollee_configurator = strcasecmp(val, "Configurator") == 0;
1136 	} else {
1137 		enrollee_ap = sigma_dut_is_ap(dut);
1138 		enrollee_configurator = 0;
1139 	}
1140 
1141 	val = get_param(cmd, "DPPNetworkRole");
1142 	if (val) {
1143 		if (strcasecmp(val, "AP") == 0) {
1144 			netrole = "ap";
1145 		} else if (strcasecmp(val, "STA") == 0) {
1146 			netrole = "sta";
1147 		} else if (strcasecmp(val, "Configurator") == 0) {
1148 			netrole = "configurator";
1149 		} else {
1150 			send_resp(dut, conn, SIGMA_ERROR,
1151 				  "errorCode,Unsupported DPPNetworkRole value");
1152 			return STATUS_SENT_ERROR;
1153 		}
1154 	}
1155 
1156 	val = get_param(cmd, "DPPChirp");
1157 	if (val)
1158 		chirp = get_enable_disable(val);
1159 
1160 	if ((step || frametype) && (!step || !frametype)) {
1161 		send_resp(dut, conn, SIGMA_ERROR,
1162 			  "errorCode,Invalid DPPStep,DPPFrameType,DPPIEAttribute combination");
1163 		return STATUS_SENT_ERROR;
1164 	}
1165 
1166 	val = get_param(cmd, "MUDURL");
1167 	if (val) {
1168 		snprintf(buf, sizeof(buf), "SET dpp_mud_url %s", val);
1169 		if (wpa_command(ifname, buf) < 0) {
1170 			send_resp(dut, conn, SIGMA_ERROR,
1171 				  "errorCode,Failed to set MUD URL");
1172 			return STATUS_SENT_ERROR;
1173 		}
1174 	}
1175 
1176 	if (sigma_dut_is_ap(dut)) {
1177 		if (!dut->hostapd_ifname) {
1178 			sigma_dut_print(dut, DUT_MSG_ERROR,
1179 					"hostapd ifname not specified (-j)");
1180 			return ERROR_SEND_STATUS;
1181 		}
1182 		ifname = dut->hostapd_ifname;
1183 
1184 		if (dpp_hostapd_run(dut) < 0) {
1185 			send_resp(dut, conn, SIGMA_ERROR,
1186 				  "errorCode,Failed to start hostapd");
1187 			return STATUS_SENT_ERROR;
1188 		}
1189 	}
1190 
1191 	if (strcasecmp(prov_role, "Configurator") == 0 ||
1192 	    strcasecmp(prov_role, "Both") == 0) {
1193 		if (dut->dpp_conf_id < 0) {
1194 			snprintf(buf, sizeof(buf),
1195 				 "DPP_CONFIGURATOR_ADD curve=%s",
1196 				 dpp_get_curve(cmd, "DPPSigningKeyECC"));
1197 			if (wpa_command_resp(ifname, buf,
1198 					     buf, sizeof(buf)) < 0) {
1199 				send_resp(dut, conn, SIGMA_ERROR,
1200 					  "errorCode,Failed to set up configurator");
1201 				return STATUS_SENT_ERROR;
1202 			}
1203 			dut->dpp_conf_id = atoi(buf);
1204 		}
1205 		if (strcasecmp(prov_role, "Configurator") == 0)
1206 			role = "configurator";
1207 		else
1208 			role = "either";
1209 	} else if (strcasecmp(prov_role, "Enrollee") == 0) {
1210 		role = "enrollee";
1211 	} else {
1212 		send_resp(dut, conn, SIGMA_ERROR,
1213 			  "errorCode,Unknown DPPProvisioningRole");
1214 		return STATUS_SENT_ERROR;
1215 	}
1216 
1217 	pkex_identifier[0] = '\0';
1218 	if (strcasecmp(bs, "PKEX") == 0) {
1219 		if (sigma_dut_is_ap(dut) && dut->ap_channel != 6) {
1220 			/* For now, have to make operating channel match DPP
1221 			 * listen channel. This should be removed once hostapd
1222 			 * has support for DPP listen on non-operating channel.
1223 			 */
1224 			sigma_dut_print(dut, DUT_MSG_INFO,
1225 					"Update hostapd operating channel to match listen needs");
1226 			dut->ap_channel = 6;
1227 
1228 			if (get_driver_type(dut) == DRIVER_OPENWRT) {
1229 				snprintf(buf, sizeof(buf),
1230 					 "iwconfig %s channel %d",
1231 					 dut->hostapd_ifname, dut->ap_channel);
1232 				run_system(dut, buf);
1233 			}
1234 
1235 			if (wpa_command(ifname, "SET channel 6") < 0 ||
1236 			    wpa_command(ifname, "DISABLE") < 0 ||
1237 			    wpa_command(ifname, "ENABLE") < 0) {
1238 				send_resp(dut, conn, SIGMA_ERROR,
1239 					  "errorCode,Failed to update channel");
1240 				return STATUS_SENT_ERROR;
1241 			}
1242 		}
1243 
1244 		if (!pkex_code) {
1245 			send_resp(dut, conn, SIGMA_ERROR,
1246 				  "errorCode,Missing DPPPKEXCode");
1247 			return STATUS_SENT_ERROR;
1248 		}
1249 
1250 		if (pkex_code_id)
1251 			snprintf(pkex_identifier, sizeof(pkex_identifier),
1252 				 "identifier=%s ", pkex_code_id);
1253 
1254 		snprintf(buf, sizeof(buf),
1255 			 "DPP_BOOTSTRAP_GEN type=pkex curve=%s",
1256 			 dpp_get_curve(cmd, "DPPCryptoIdentifier"));
1257 		if (wpa_command_resp(ifname, buf, buf, sizeof(buf)) < 0) {
1258 			send_resp(dut, conn, SIGMA_ERROR,
1259 				  "errorCode,Failed to set up PKEX");
1260 			return STATUS_SENT_ERROR;
1261 		}
1262 		own_pkex_id = atoi(buf);
1263 	}
1264 
1265 	ctrl = open_wpa_mon(ifname);
1266 	if (!ctrl) {
1267 		sigma_dut_print(dut, DUT_MSG_ERROR,
1268 				"Failed to open wpa_supplicant monitor connection");
1269 		return ERROR_SEND_STATUS;
1270 	}
1271 
1272 	old_timeout = dut->default_timeout;
1273 	val = get_param(cmd, "DPPTimeout");
1274 	if (val && atoi(val) > 0) {
1275 		dut->default_timeout = atoi(val);
1276 		sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP timeout: %u",
1277 				dut->default_timeout);
1278 	}
1279 
1280 	val = get_param(cmd, "DPPStatusQuery");
1281 	conn_status = val && strcasecmp(val, "Yes") == 0;
1282 
1283 	conf_ssid[0] = '\0';
1284 	conf_pass[0] = '\0';
1285 	csrattrs[0] = '\0';
1286 	group_id[0] = '\0';
1287 	conf2[0] = '\0';
1288 	if (!enrollee_configurator) {
1289 		val = get_param(cmd, "DPPConfIndex");
1290 		if (val)
1291 			conf_index = atoi(val);
1292 	}
1293 	switch (conf_index) {
1294 	case -1:
1295 		if (enrollee_configurator)
1296 			conf_role = "configurator";
1297 		else
1298 			conf_role = NULL;
1299 		break;
1300 	case 1:
1301 		ascii2hexstr("DPPNET01", buf);
1302 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
1303 		if (res < 0 || res >= sizeof(conf_ssid))
1304 			goto err;
1305 		if (enrollee_ap) {
1306 			conf_role = "ap-dpp";
1307 		} else {
1308 			conf_role = "sta-dpp";
1309 		}
1310 		group_id_str = "DPPGROUP_DPP_INFRA";
1311 		break;
1312 	case 2:
1313 		ascii2hexstr("DPPNET01", buf);
1314 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
1315 		if (res < 0 || res >= sizeof(conf_ssid))
1316 			goto err;
1317 		snprintf(conf_pass, sizeof(conf_pass),
1318 			 "psk=10506e102ad1e7f95112f6b127675bb8344dacacea60403f3fa4055aec85b0fc");
1319 		if (enrollee_ap)
1320 			conf_role = "ap-psk";
1321 		else
1322 			conf_role = "sta-psk";
1323 		break;
1324 	case 3:
1325 		ascii2hexstr("DPPNET01", buf);
1326 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
1327 		if (res < 0 || res >= sizeof(conf_ssid))
1328 			goto err;
1329 		ascii2hexstr("ThisIsDppPassphrase", buf);
1330 		res = snprintf(conf_pass, sizeof(conf_pass), "pass=%s", buf);
1331 		if (res < 0 || res >= sizeof(conf_pass))
1332 			goto err;
1333 		if (enrollee_ap)
1334 			conf_role = "ap-psk";
1335 		else
1336 			conf_role = "sta-psk";
1337 		break;
1338 	case 4:
1339 		ascii2hexstr("DPPNET01", buf);
1340 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
1341 		if (res < 0 || res >= sizeof(conf_ssid))
1342 			goto err;
1343 		if (enrollee_ap) {
1344 			conf_role = "ap-dpp";
1345 		} else {
1346 			conf_role = "sta-dpp";
1347 		}
1348 		group_id_str = "DPPGROUP_DPP_INFRA2";
1349 		break;
1350 	case 5:
1351 		ascii2hexstr("DPPNET01", buf);
1352 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
1353 		if (res < 0 || res >= sizeof(conf_ssid))
1354 			goto err;
1355 		ascii2hexstr("ThisIsDppPassphrase", buf);
1356 		res = snprintf(conf_pass, sizeof(conf_pass), "pass=%s", buf);
1357 		if (res < 0 || res >= sizeof(conf_pass))
1358 			goto err;
1359 		if (enrollee_ap)
1360 			conf_role = "ap-sae";
1361 		else
1362 			conf_role = "sta-sae";
1363 		break;
1364 	case 6:
1365 		ascii2hexstr("DPPNET01", buf);
1366 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
1367 		if (res < 0 || res >= sizeof(conf_ssid))
1368 			goto err;
1369 		ascii2hexstr("ThisIsDppPassphrase", buf);
1370 		res = snprintf(conf_pass, sizeof(conf_pass), "pass=%s", buf);
1371 		if (res < 0 || res >= sizeof(conf_pass))
1372 			goto err;
1373 		if (enrollee_ap)
1374 			conf_role = "ap-psk-sae";
1375 		else
1376 			conf_role = "sta-psk-sae";
1377 		break;
1378 	case 7:
1379 		ascii2hexstr("DPPNET01", buf);
1380 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
1381 		if (res < 0 || res >= sizeof(conf_ssid))
1382 			goto err;
1383 		if (enrollee_ap) {
1384 			conf_role = "ap-dpp";
1385 		} else {
1386 			conf_role = "sta-dpp";
1387 		}
1388 		group_id_str = "DPPGROUP_DPP_INFRA";
1389 		force_gas_fragm = 1;
1390 		break;
1391 	case 8:
1392 	case 9:
1393 		ascii2hexstr("DPPNET01", buf);
1394 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
1395 		if (res < 0 || res >= sizeof(conf_ssid))
1396 			goto err;
1397 		ascii2hexstr("This_is_legacy_password", buf);
1398 		res = snprintf(conf_pass, sizeof(conf_pass), "pass=%s", buf);
1399 		if (res < 0 || res >= sizeof(conf_pass))
1400 			goto err;
1401 		if (enrollee_ap) {
1402 			conf_role = "ap-dpp+psk+sae";
1403 		} else {
1404 			conf_role = "sta-dpp+psk+sae";
1405 		}
1406 		group_id_str = "DPPGROUP_DPP_INFRA1";
1407 		if (conf_index == 9)
1408 			akm_use_selector = 1;
1409 		break;
1410 	case 10:
1411 		ascii2hexstr("DPPNET01", buf);
1412 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
1413 		if (res < 0 || res >= sizeof(conf_ssid))
1414 			goto err;
1415 		if (enrollee_ap)
1416 			conf_role = "ap-dpp";
1417 		else
1418 			conf_role = "sta-dpp";
1419 		group_id_str = "DPPGROUP_DPP_INFRA1";
1420 		ascii2hexstr("DPPNET02", buf);
1421 		ascii2hexstr("This_is_legacy_password", buf2);
1422 		res = snprintf(conf2, sizeof(conf2),
1423 			       " @CONF-OBJ-SEP@ conf=%s-dpp+psk+sae ssid=%s pass=%s group_id=DPPGROUP_DPP_INFRA2",
1424 			       enrollee_ap ? "ap" : "sta", buf, buf2);
1425 		if (res < 0 || res >= sizeof(conf2))
1426 			goto err;
1427 		break;
1428 	case 11:
1429 		ascii2hexstr("DPPNET01", buf);
1430 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
1431 		if (res < 0 || res >= sizeof(conf_ssid))
1432 			goto err;
1433 		if (enrollee_ap) {
1434 			send_resp(dut, conn, SIGMA_ERROR,
1435 				  "errorCode,dot1x AKM provisioning not supported for AP");
1436 			goto out;
1437 		}
1438 		conf_role = "sta-dot1x";
1439 		snprintf(buf, sizeof(buf), "%s/dpp-ca-csrattrs",
1440 			 sigma_cert_path);
1441 		f = fopen(buf, "r");
1442 		if (f) {
1443 			size_t len;
1444 			int r;
1445 
1446 			len = fread(buf, 1, sizeof(buf), f);
1447 			fclose(f);
1448 			if (len >= sizeof(buf)) {
1449 				send_resp(dut, conn, SIGMA_ERROR,
1450 					  "errorCode,No room for csrAttrs");
1451 				goto out;
1452 			}
1453 			buf[len] = '\0';
1454 			sigma_dut_print(dut, DUT_MSG_INFO,
1455 					"Use csrAttrs from file");
1456 			r = snprintf(csrattrs, sizeof(csrattrs),
1457 				     " csrattrs=%s", buf);
1458 			if (r <= 0 || r >= sizeof(csrattrs)) {
1459 				send_resp(dut, conn, SIGMA_ERROR,
1460 					  "errorCode,No room for csrAttrs");
1461 				goto out;
1462 			}
1463 		} else {
1464 			sigma_dut_print(dut, DUT_MSG_INFO,
1465 					"Use default csrAttrs");
1466 			snprintf(csrattrs, sizeof(csrattrs), "%s",
1467 				 " csrattrs=MAsGCSqGSIb3DQEJBw==");
1468 		}
1469 		break;
1470 	default:
1471 		send_resp(dut, conn, SIGMA_ERROR,
1472 			  "errorCode,Unsupported DPPConfIndex");
1473 		goto out;
1474 	}
1475 
1476 	if (group_id_str)
1477 		snprintf(group_id, sizeof(group_id), " group_id=%s",
1478 			 group_id_str);
1479 
1480 	if (force_gas_fragm) {
1481 		char spaces[1500];
1482 
1483 		memset(spaces, ' ', sizeof(spaces));
1484 		spaces[sizeof(spaces) - 1] = '\0';
1485 
1486 		snprintf(buf, sizeof(buf),
1487 			 "SET dpp_discovery_override {\"ssid\":\"DPPNET01\"}%s",
1488 			 spaces);
1489 		if (wpa_command(ifname, buf) < 0) {
1490 			send_resp(dut, conn, SIGMA_ERROR,
1491 				  "errorCode,Failed to set discovery override");
1492 			goto out;
1493 		}
1494 	}
1495 
1496 	if (step) {
1497 		int test;
1498 
1499 		test = dpp_get_test(step, frametype, attr);
1500 		if (test <= 0) {
1501 			send_resp(dut, conn, SIGMA_ERROR,
1502 				  "errorCode,Unsupported DPPStep/DPPFrameType/DPPIEAttribute");
1503 			goto out;
1504 		}
1505 
1506 		snprintf(buf, sizeof(buf), "SET dpp_test %d", test);
1507 		if (wpa_command(ifname, buf) < 0) {
1508 			send_resp(dut, conn, SIGMA_ERROR,
1509 				  "errorCode,Failed to set dpp_test");
1510 			goto out;
1511 		}
1512 	} else {
1513 		wpa_command(ifname, "SET dpp_test 0");
1514 	}
1515 
1516 	if (strcasecmp(self_conf, "Yes") == 0) {
1517 		if (strcasecmp(prov_role, "Configurator") != 0) {
1518 			send_resp(dut, conn, SIGMA_ERROR,
1519 				  "errorCode,Invalid DPPSelfConfigure use - only allowed for Configurator role");
1520 			goto out;
1521 		}
1522 		if (!conf_role) {
1523 			send_resp(dut, conn, SIGMA_ERROR,
1524 				  "errorCode,Missing DPPConfIndex");
1525 			goto out;
1526 		}
1527 
1528 		snprintf(buf, sizeof(buf),
1529 			 "DPP_CONFIGURATOR_SIGN  conf=%s %s %s configurator=%d",
1530 			 conf_role, conf_ssid, conf_pass, dut->dpp_conf_id);
1531 		if (wpa_command(ifname, buf) < 0) {
1532 			send_resp(dut, conn, SIGMA_ERROR,
1533 				  "errorCode,Failed to initiate DPP self-configuration");
1534 			goto out;
1535 		}
1536 		if (sigma_dut_is_ap(dut))
1537 			goto update_ap;
1538 		goto wait_connect;
1539 	} else if (manual && strcasecmp(bs, "NFC") == 0) {
1540 		const char *val = get_param(cmd, "DPPNFCInit");
1541 		int init = !val || atoi(val) > 0;
1542 		pid_t pid;
1543 		int pid_status;
1544 		int enrollee = 0;
1545 		int tag_read = 0;
1546 		int tag_write_uri = 0;
1547 		int tag_write_hs = 0;
1548 		const char *tx_rx_events[] = { "DPP-TX", "DPP-RX", NULL };
1549 		const char *chan_list, *alt_chan_list;
1550 		char chan_list2[200], alt_chan_list2[200];
1551 
1552 		if (strcasecmp(prov_role, "Configurator") == 0 ||
1553 		    strcasecmp(prov_role, "Both") == 0) {
1554 			if (!conf_role) {
1555 				send_resp(dut, conn, SIGMA_ERROR,
1556 					  "errorCode,Missing DPPConfIndex");
1557 				goto out;
1558 			}
1559 			snprintf(buf, sizeof(buf),
1560 				 "SET dpp_configurator_params  conf=%s %s %s configurator=%d%s%s%s%s%s",
1561 				 conf_role, conf_ssid, conf_pass,
1562 				 dut->dpp_conf_id, group_id,
1563 				 akm_use_selector ? " akm_use_selector=1" : "",
1564 				 conn_status ? " conn_status=1" : "",
1565 				 csrattrs, conf2);
1566 			if (wpa_command(ifname, buf) < 0) {
1567 				send_resp(dut, conn, SIGMA_ERROR,
1568 					  "errorCode,Failed to set configurator parameters");
1569 				goto out;
1570 			}
1571 			snprintf(buf, sizeof(buf),
1572 				 "conf=%s %s %s configurator=%d%s%s%s%s%s",
1573 				 conf_role, conf_ssid, conf_pass,
1574 				 dut->dpp_conf_id, group_id,
1575 				 akm_use_selector ? " akm_use_selector=1" : "",
1576 				 conn_status ? " conn_status=1" : "", csrattrs,
1577 				 conf2);
1578 		} else {
1579 			buf[0] = '\0';
1580 			enrollee = 1;
1581 		}
1582 
1583 		val = get_param(cmd, "DPPNFCTag");
1584 		if (val) {
1585 			if (strcasecmp(val, "Read") == 0) {
1586 				tag_read = 1;
1587 			} else if (strcasecmp(val, "Write-HS") == 0) {
1588 				tag_write_hs = 1;
1589 			} else if (strcasecmp(val, "Write-URI") == 0) {
1590 				tag_write_uri = 1;
1591 			} else {
1592 				send_resp(dut, conn, SIGMA_ERROR,
1593 					  "errorCode,Unsupported DPPNFCTag value");
1594 				goto out;
1595 			}
1596 		}
1597 
1598 		chan_list = get_param(cmd, "DPPChannelList");
1599 		if (chan_list) {
1600 			strlcpy(chan_list2, chan_list, sizeof(chan_list2));
1601 			for (pos = chan_list2; *pos; pos++) {
1602 				if (*pos == ' ')
1603 					*pos = ',';
1604 			}
1605 		}
1606 		alt_chan_list = get_param(cmd, "DPPNFCAltChannelList");
1607 		if (alt_chan_list) {
1608 			strlcpy(alt_chan_list2, alt_chan_list,
1609 				sizeof(alt_chan_list2));
1610 			for (pos = alt_chan_list2; *pos; pos++) {
1611 				if (*pos == ' ')
1612 					*pos = ',';
1613 			}
1614 		}
1615 
1616 		run_system(dut, "killall dpp-nfc.py");
1617 		sigma_dut_print(dut, DUT_MSG_INFO, "Manual NFC operation");
1618 		if (!file_exists("dpp-nfc.py")) {
1619 			send_resp(dut, conn, SIGMA_ERROR,
1620 				  "errorCode,dpp-nfc.py not found");
1621 			goto out;
1622 		}
1623 
1624 		pid = fork();
1625 		if (pid < 0) {
1626 			perror("fork");
1627 			send_resp(dut, conn, SIGMA_ERROR,
1628 				  "errorCode,fork() failed");
1629 			goto out;
1630 		}
1631 
1632 		if (pid == 0) {
1633 			char *argv[100];
1634 			int pos = 0;
1635 
1636 			argv[pos++] = "dpp-nfc.py";
1637 			argv[pos++] = "--only-one";
1638 			argv[pos++] = "--no-input";
1639 			argv[pos++] = "-i";
1640 			argv[pos++] = (char *) ifname;
1641 			argv[pos++] = "--ctrl";
1642 			argv[pos++] = sigma_wpas_ctrl;
1643 			argv[pos++] = enrollee ? "--enrollee" :
1644 				"--configurator";
1645 			argv[pos++] = "--config-params";
1646 			argv[pos++] = buf;
1647 			if (chan_list && strcmp(chan_list, "0/0") != 0) {
1648 				argv[pos++] = "--chan";
1649 				argv[pos++] = chan_list2;
1650 			}
1651 			if (alt_chan_list &&
1652 			    strcmp(alt_chan_list, "0/0") != 0) {
1653 				argv[pos++] = "--altchan";
1654 				argv[pos++] = alt_chan_list2;
1655 			}
1656 			if (init)
1657 				argv[pos++] = "-I";
1658 			if (netrole) {
1659 				argv[pos++] = "--netrole";
1660 				argv[pos++] = (char *) netrole;
1661 			}
1662 			if (tag_read || tag_write_hs || tag_write_uri)
1663 				argv[pos++] = "--no-wait";
1664 			if (!tag_read && !tag_write_hs && !tag_write_uri)
1665 				argv[pos++] = "--handover-only";
1666 			if (tag_read)
1667 				argv[pos++] = "--tag-read-only";
1668 			else if (tag_write_hs)
1669 				argv[pos++] = "write-nfc-hs";
1670 			else if (tag_write_uri)
1671 				argv[pos++] = "write-nfc-uri";
1672 			argv[pos] = NULL;
1673 
1674 			execv("./dpp-nfc.py", argv);
1675 			perror("execv");
1676 			exit(0);
1677 			return -1;
1678 		}
1679 
1680 		usleep(300000);
1681 		for (;;) {
1682 			if (waitpid(pid, &pid_status, WNOHANG) > 0) {
1683 				int status = WEXITSTATUS(pid_status);
1684 
1685 				sigma_dut_print(dut, DUT_MSG_DEBUG,
1686 						"dpp-nfc.py exited (status %d)",
1687 						status);
1688 				if (status == 1) {
1689 					send_resp(dut, conn, SIGMA_ERROR,
1690 						  "errorCode,dpp-nfc.py operation failed");
1691 					goto out;
1692 				}
1693 				break;
1694 			}
1695 
1696 			time(&now);
1697 			if ((unsigned int) (now - start) >=
1698 			    dut->default_timeout) {
1699 				sigma_dut_print(dut, DUT_MSG_DEBUG,
1700 						"dpp-nfc.py did not exit within timeout - stop it");
1701 				kill(pid, SIGTERM);
1702 				waitpid(pid, &pid_status, 0);
1703 				send_resp(dut, conn, SIGMA_ERROR,
1704 					  "errorCode,dpp-nfc.py did not complete within timeout");
1705 				goto out;
1706 			}
1707 
1708 			old_timeout = dut->default_timeout;
1709 			dut->default_timeout = 2;
1710 
1711 			res = get_wpa_cli_events(dut, ctrl, tx_rx_events,
1712 						buf, sizeof(buf));
1713 			dut->default_timeout = old_timeout;
1714 			if (res >= 0) {
1715 				sigma_dut_print(dut, DUT_MSG_DEBUG,
1716 						"DPP exchange started");
1717 				usleep(500000);
1718 				kill(pid, SIGTERM);
1719 				waitpid(pid, &pid_status, 0);
1720 				break;
1721 			}
1722 		}
1723 	} else if ((nfc_handover &&
1724 		    strcasecmp(nfc_handover, "Negotiated_Requestor") == 0) ||
1725 		   ((!nfc_handover ||
1726 		     strcasecmp(nfc_handover, "Static") == 0) &&
1727 		    auth_role && strcasecmp(auth_role, "Initiator") == 0)) {
1728 		char own_txt[20];
1729 		int dpp_peer_bootstrap = -1;
1730 		char neg_freq[30];
1731 
1732 		val = get_param(cmd, "DPPAuthDirection");
1733 		check_mutual = val && strcasecmp(val, "Mutual") == 0;
1734 
1735 		neg_freq[0] = '\0';
1736 		val = get_param(cmd, "DPPSubsequentChannel");
1737 		if (val) {
1738 			int opclass, channel, freq;
1739 
1740 			opclass = atoi(val);
1741 			val = strchr(val, '/');
1742 			if (opclass == 0 || !val) {
1743 				send_resp(dut, conn, SIGMA_ERROR,
1744 					  "errorCode,Invalid DPPSubsequentChannel");
1745 				goto out;
1746 			}
1747 			val++;
1748 			channel = atoi(val);
1749 
1750 			/* Ignoring opclass for now; could use it here for more
1751 			 * robust frequency determination. */
1752 			freq = channel_to_freq(dut, channel);
1753 			if (!freq) {
1754 				send_resp(dut, conn, SIGMA_ERROR,
1755 					  "errorCode,Unsupported DPPSubsequentChannel channel");
1756 				goto out;
1757 			}
1758 			snprintf(neg_freq, sizeof(neg_freq), " neg_freq=%d",
1759 				 freq);
1760 		}
1761 
1762 		if (strcasecmp(bs, "QR") == 0) {
1763 			if (!dut->dpp_peer_uri) {
1764 				send_resp(dut, conn, SIGMA_ERROR,
1765 					  "errorCode,Missing peer bootstrapping info");
1766 				goto out;
1767 			}
1768 
1769 			snprintf(buf, sizeof(buf), "DPP_QR_CODE %s",
1770 				 dut->dpp_peer_uri);
1771 			if (wpa_command_resp(ifname, buf, buf,
1772 					     sizeof(buf)) < 0 ||
1773 			    strncmp(buf, "FAIL", 4) == 0) {
1774 				send_resp(dut, conn, SIGMA_ERROR,
1775 					  "errorCode,Failed to parse URI");
1776 				goto out;
1777 			}
1778 			dpp_peer_bootstrap = atoi(buf);
1779 		} else if (strcasecmp(bs, "NFC") == 0 && nfc_handover &&
1780 			   strcasecmp(nfc_handover, "Static") == 0) {
1781 			if (!dut->dpp_peer_uri) {
1782 				send_resp(dut, conn, SIGMA_ERROR,
1783 					  "errorCode,Missing peer bootstrapping info");
1784 				goto out;
1785 			}
1786 
1787 			snprintf(buf, sizeof(buf), "DPP_NFC_URI %s",
1788 				 dut->dpp_peer_uri);
1789 			if (wpa_command_resp(ifname, buf,
1790 					     buf, sizeof(buf)) < 0 ||
1791 			    strncmp(buf, "FAIL", 4) == 0) {
1792 				send_resp(dut, conn, SIGMA_ERROR,
1793 					  "errorCode,Failed to process URI from NFC Tag");
1794 				goto out;
1795 			}
1796 			dpp_peer_bootstrap = atoi(buf);
1797 		} else if (strcasecmp(bs, "NFC") == 0) {
1798 			if (!dut->dpp_peer_uri) {
1799 				send_resp(dut, conn, SIGMA_ERROR,
1800 					  "errorCode,Missing peer bootstrapping info");
1801 				goto out;
1802 			}
1803 			if (dut->dpp_local_bootstrap < 0) {
1804 				send_resp(dut, conn, SIGMA_ERROR,
1805 					  "errorCode,Missing own bootstrapping info");
1806 				goto out;
1807 			}
1808 
1809 			snprintf(buf, sizeof(buf),
1810 				 "DPP_NFC_HANDOVER_SEL own=%d uri=%s",
1811 				 dut->dpp_local_bootstrap, dut->dpp_peer_uri);
1812 			if (wpa_command_resp(ifname, buf,
1813 					     buf, sizeof(buf)) < 0 ||
1814 			    strncmp(buf, "FAIL", 4) == 0) {
1815 				send_resp(dut, conn, SIGMA_ERROR,
1816 					  "errorCode,Failed to process NFC Handover Select");
1817 				goto out;
1818 			}
1819 			dpp_peer_bootstrap = atoi(buf);
1820 		}
1821 
1822 		if (dut->dpp_local_bootstrap >= 0)
1823 			snprintf(own_txt, sizeof(own_txt), " own=%d",
1824 				 dut->dpp_local_bootstrap);
1825 		else
1826 			own_txt[0] = '\0';
1827 		if (chirp) {
1828 			int freq = 2437; /* default: channel 6 */
1829 
1830 			val = get_param(cmd, "DPPChirpChannel");
1831 			if (val) {
1832 				freq = channel_to_freq(dut, atoi(val));
1833 				if (!freq) {
1834 					send_resp(dut, conn, SIGMA_ERROR,
1835 						  "errorCode,Unsupported DPPChirpChannel channel");
1836 					goto out;
1837 				}
1838 			}
1839 
1840 			if (strcasecmp(prov_role, "Configurator") == 0 ||
1841 			    strcasecmp(prov_role, "Both") == 0) {
1842 				if (!conf_role) {
1843 					send_resp(dut, conn, SIGMA_ERROR,
1844 						  "errorCode,Missing DPPConfIndex");
1845 					goto out;
1846 				}
1847 				snprintf(buf, sizeof(buf),
1848 					 "SET dpp_configurator_params  conf=%s %s %s configurator=%d%s%s%s%s%s",
1849 					 conf_role, conf_ssid, conf_pass,
1850 					 dut->dpp_conf_id, group_id,
1851 					 akm_use_selector ?
1852 					 " akm_use_selector=1" : "",
1853 					 conn_status ? " conn_status=1" : "",
1854 					 csrattrs, conf2);
1855 				if (wpa_command(ifname, buf) < 0) {
1856 					send_resp(dut, conn, SIGMA_ERROR,
1857 						  "errorCode,Failed to set configurator parameters");
1858 					goto out;
1859 				}
1860 			}
1861 
1862 			if (tcp && strcasecmp(tcp, "yes") == 0) {
1863 				snprintf(buf, sizeof(buf),
1864 					 "DPP_CONTROLLER_START");
1865 			} else {
1866 				snprintf(buf, sizeof(buf),
1867 					 "DPP_LISTEN %d role=%s%s%s",
1868 					 freq, role,
1869 					 netrole ? " netrole=" : "",
1870 					 netrole ? netrole : "");
1871 			}
1872 		} else if ((strcasecmp(bs, "QR") == 0 ||
1873 			    strcasecmp(bs, "NFC") == 0) &&
1874 			   (strcasecmp(prov_role, "Configurator") == 0 ||
1875 			    strcasecmp(prov_role, "Both") == 0)) {
1876 			if (!conf_role) {
1877 				send_resp(dut, conn, SIGMA_ERROR,
1878 					  "errorCode,Missing DPPConfIndex");
1879 				goto out;
1880 			}
1881 			snprintf(buf, sizeof(buf),
1882 				 "DPP_AUTH_INIT peer=%d%s role=%s%s%s conf=%s %s %s configurator=%d%s%s%s%s%s%s%s%s",
1883 				 dpp_peer_bootstrap, own_txt, role,
1884 				 netrole ? " netrole=" : "",
1885 				 netrole ? netrole : "",
1886 				 conf_role, conf_ssid, conf_pass,
1887 				 dut->dpp_conf_id, neg_freq, group_id,
1888 				 akm_use_selector ? " akm_use_selector=1" : "",
1889 				 conn_status ? " conn_status=1" : "",
1890 				 tcp ? " tcp_addr=" : "",
1891 				 tcp ? tcp : "",
1892 				 csrattrs, conf2);
1893 		} else if (tcp && (strcasecmp(bs, "QR") == 0 ||
1894 				   strcasecmp(bs, "NFC") == 0)) {
1895 			snprintf(buf, sizeof(buf),
1896 				 "DPP_AUTH_INIT peer=%d%s role=%s%s%s tcp_addr=%s%s%s",
1897 				 dpp_peer_bootstrap, own_txt, role,
1898 				 netrole ? " netrole=" : "",
1899 				 netrole ? netrole : "",
1900 				 tcp, neg_freq, group_id);
1901 		} else if (strcasecmp(bs, "QR") == 0 ||
1902 			   strcasecmp(bs, "NFC") == 0) {
1903 			snprintf(buf, sizeof(buf),
1904 				 "DPP_AUTH_INIT peer=%d%s role=%s%s%s%s%s",
1905 				 dpp_peer_bootstrap, own_txt, role,
1906 				 netrole ? " netrole=" : "",
1907 				 netrole ? netrole : "",
1908 				 neg_freq, group_id);
1909 		} else if (strcasecmp(bs, "PKEX") == 0 &&
1910 			   (strcasecmp(prov_role, "Configurator") == 0 ||
1911 			    strcasecmp(prov_role, "Both") == 0)) {
1912 			if (!conf_role) {
1913 				send_resp(dut, conn, SIGMA_ERROR,
1914 					  "errorCode,Missing DPPConfIndex");
1915 				goto out;
1916 			}
1917 			snprintf(buf, sizeof(buf),
1918 				 "DPP_PKEX_ADD own=%d init=1 role=%s conf=%s %s %s configurator=%d%s %scode=%s",
1919 				 own_pkex_id, role, conf_role,
1920 				 conf_ssid, conf_pass, dut->dpp_conf_id,
1921 				 csrattrs, pkex_identifier, pkex_code);
1922 		} else if (strcasecmp(bs, "PKEX") == 0) {
1923 			snprintf(buf, sizeof(buf),
1924 				 "DPP_PKEX_ADD own=%d init=1 role=%s %scode=%s",
1925 				 own_pkex_id, role, pkex_identifier, pkex_code);
1926 		} else {
1927 			send_resp(dut, conn, SIGMA_ERROR,
1928 				  "errorCode,Unsupported DPPBS");
1929 			goto out;
1930 		}
1931 		if (wpa_command(ifname, buf) < 0) {
1932 			send_resp(dut, conn, SIGMA_ERROR,
1933 				  "errorCode,Failed to initiate DPP authentication");
1934 			goto out;
1935 		}
1936 	} else if ((nfc_handover &&
1937 		    strcasecmp(nfc_handover, "Negotiated_Selector") == 0) ||
1938 		   ((!nfc_handover ||
1939 		     strcasecmp(nfc_handover, "Static") == 0) &&
1940 		    auth_role && strcasecmp(auth_role, "Responder") == 0)) {
1941 		const char *delay_qr_resp;
1942 		int mutual;
1943 		int freq = 2462; /* default: channel 11 */
1944 
1945 		if (sigma_dut_is_ap(dut) && dut->hostapd_running &&
1946 		    dut->ap_oper_chn)
1947 			freq = channel_to_freq(dut, dut->ap_channel);
1948 
1949 		if (strcasecmp(bs, "PKEX") == 0) {
1950 			/* default: channel 6 for PKEX */
1951 			freq = 2437;
1952 		}
1953 
1954 		delay_qr_resp = get_param(cmd, "DPPDelayQRResponse");
1955 
1956 		val = get_param(cmd, "DPPAuthDirection");
1957 		mutual = val && strcasecmp(val, "Mutual") == 0;
1958 
1959 		val = get_param(cmd, "DPPListenChannel");
1960 		if (val) {
1961 			freq = channel_to_freq(dut, atoi(val));
1962 			if (freq == 0) {
1963 				send_resp(dut, conn, SIGMA_ERROR,
1964 					  "errorCode,Unsupported DPPListenChannel value");
1965 				goto out;
1966 			}
1967 
1968 			if (sigma_dut_is_ap(dut) && !chirp &&
1969 			    dut->ap_start_disabled &&
1970 			    atoi(val) != dut->ap_channel) {
1971 				sigma_dut_print(dut, DUT_MSG_INFO,
1972 						"Use requested listen channel as the initial operating channel");
1973 				snprintf(buf, sizeof(buf), "SET channel %d",
1974 					 atoi(val));
1975 				wpa_command(ifname, buf);
1976 			}
1977 		}
1978 
1979 		if (sigma_dut_is_ap(dut) && dpp_hostapd_beacon(dut) < 0) {
1980 			send_resp(dut, conn, SIGMA_ERROR,
1981 				  "errorCode,Failed to start AP mode listen");
1982 			goto out;
1983 		}
1984 
1985 		if (strcasecmp(bs, "NFC") == 0 && nfc_handover &&
1986 		    strcasecmp(nfc_handover, "Static") == 0) {
1987 			/* No steps needed here - waiting for peer to initiate
1988 			 * once it reads the URI from the NFC Tag */
1989 		} else if (strcasecmp(bs, "NFC") == 0) {
1990 			if (!dut->dpp_peer_uri) {
1991 				send_resp(dut, conn, SIGMA_ERROR,
1992 					  "errorCode,Missing peer bootstrapping info");
1993 				goto out;
1994 			}
1995 			if (dut->dpp_local_bootstrap < 0) {
1996 				send_resp(dut, conn, SIGMA_ERROR,
1997 					  "errorCode,Missing own bootstrapping info");
1998 				goto out;
1999 			}
2000 
2001 			snprintf(buf, sizeof(buf),
2002 				 "DPP_NFC_HANDOVER_REQ own=%d uri=%s",
2003 				 dut->dpp_local_bootstrap, dut->dpp_peer_uri);
2004 			if (wpa_command(ifname, buf) < 0) {
2005 				send_resp(dut, conn, SIGMA_ERROR,
2006 					  "errorCode,Failed to process NFC Handover Request");
2007 				goto out;
2008 			}
2009 
2010 			snprintf(buf, sizeof(buf), "DPP_BOOTSTRAP_INFO %d",
2011 				 dut->dpp_local_bootstrap);
2012 			if (wpa_command_resp(ifname, buf,
2013 					     buf, sizeof(buf)) < 0 ||
2014 			    strncmp(buf, "FAIL", 4) == 0) {
2015 				send_resp(dut, conn, SIGMA_ERROR,
2016 					  "errorCode,Failed to get bootstrap information");
2017 				goto out;
2018 			}
2019 			pos = buf;
2020 			while (pos) {
2021 				pos2 = strchr(pos, '\n');
2022 				if (pos2)
2023 					*pos2 = '\0';
2024 				if (strncmp(pos, "use_freq=", 9) == 0) {
2025 					freq = atoi(pos + 9);
2026 					sigma_dut_print(dut, DUT_MSG_DEBUG,
2027 							"DPP negotiation frequency from NFC handover: %d MHz",
2028 							freq);
2029 					break;
2030 				}
2031 
2032 				if (!pos2)
2033 					break;
2034 				pos = pos2 + 1;
2035 			}
2036 		} else if (!delay_qr_resp && dut->dpp_peer_uri) {
2037 			snprintf(buf, sizeof(buf), "DPP_QR_CODE %s",
2038 				 dut->dpp_peer_uri);
2039 			if (wpa_command_resp(ifname, buf, buf,
2040 					     sizeof(buf)) < 0) {
2041 				send_resp(dut, conn, SIGMA_ERROR,
2042 					  "errorCode,Failed to parse URI");
2043 				goto out;
2044 			}
2045 		}
2046 
2047 		if (strcasecmp(prov_role, "Configurator") == 0) {
2048 			if (!conf_role) {
2049 				send_resp(dut, conn, SIGMA_ERROR,
2050 					  "errorCode,Missing DPPConfIndex");
2051 				goto out;
2052 			}
2053 			snprintf(buf, sizeof(buf),
2054 				 "SET dpp_configurator_params  conf=%s %s %s configurator=%d%s%s%s%s%s",
2055 				 conf_role, conf_ssid, conf_pass,
2056 				 dut->dpp_conf_id, group_id,
2057 				 akm_use_selector ? " akm_use_selector=1" : "",
2058 				 conn_status ? " conn_status=1" : "", csrattrs,
2059 				 conf2);
2060 			if (wpa_command(ifname, buf) < 0) {
2061 				send_resp(dut, conn, SIGMA_ERROR,
2062 					  "errorCode,Failed to set configurator parameters");
2063 				goto out;
2064 			}
2065 		}
2066 		if (strcasecmp(bs, "PKEX") == 0) {
2067 			snprintf(buf, sizeof(buf),
2068 				 "DPP_PKEX_ADD own=%d role=%s %scode=%s",
2069 				 own_pkex_id, role, pkex_identifier, pkex_code);
2070 			if (wpa_command(ifname, buf) < 0) {
2071 				send_resp(dut, conn, SIGMA_ERROR,
2072 					  "errorCode,Failed to configure DPP PKEX");
2073 				goto out;
2074 			}
2075 		}
2076 
2077 		if (chirp) {
2078 			snprintf(buf, sizeof(buf),
2079 				 "DPP_CHIRP own=%d iter=10 listen=%d",
2080 				 dut->dpp_local_bootstrap, freq);
2081 		} else if (tcp && strcasecmp(tcp, "yes") == 0) {
2082 			snprintf(buf, sizeof(buf), "DPP_CONTROLLER_START");
2083 		} else {
2084 			snprintf(buf, sizeof(buf),
2085 				 "DPP_LISTEN %d role=%s%s%s%s",
2086 				 freq, role,
2087 				 (strcasecmp(bs, "QR") == 0 && mutual) ?
2088 				 " qr=mutual" : "",
2089 				 netrole ? " netrole=" : "",
2090 				 netrole ? netrole : "");
2091 		}
2092 		if (wpa_command(ifname, buf) < 0) {
2093 			send_resp(dut, conn, SIGMA_ERROR,
2094 				  "errorCode,Failed to start DPP listen/chirp");
2095 			goto out;
2096 		}
2097 
2098 		if (!(tcp && strcasecmp(tcp, "yes") == 0) &&
2099 		    get_driver_type(dut) == DRIVER_OPENWRT) {
2100 			snprintf(buf, sizeof(buf), "iwconfig %s channel %d",
2101 				 dut->hostapd_ifname, freq_to_channel(freq));
2102 			run_system(dut, buf);
2103 		}
2104 
2105 		if (delay_qr_resp && mutual && dut->dpp_peer_uri) {
2106 			int wait_time = atoi(delay_qr_resp);
2107 
2108 			res = get_wpa_cli_events(dut, ctrl, auth_events,
2109 						 buf, sizeof(buf));
2110 			if (res < 0) {
2111 				send_resp(dut, conn, SIGMA_COMPLETE,
2112 					  "BootstrapResult,OK,AuthResult,Timeout");
2113 				goto out;
2114 			}
2115 			sigma_dut_print(dut, DUT_MSG_DEBUG,
2116 					"DPP auth result: %s", buf);
2117 			if (strstr(buf, "DPP-SCAN-PEER-QR-CODE") == NULL) {
2118 				send_resp(dut, conn, SIGMA_ERROR,
2119 					  "errorCode,No scan request for peer QR Code seen");
2120 				goto out;
2121 			}
2122 			sigma_dut_print(dut, DUT_MSG_INFO,
2123 					"Waiting %d second(s) before processing peer URI",
2124 					wait_time);
2125 			sleep(wait_time);
2126 
2127 			snprintf(buf, sizeof(buf), "DPP_QR_CODE %s",
2128 				 dut->dpp_peer_uri);
2129 			if (wpa_command_resp(ifname, buf, buf,
2130 					     sizeof(buf)) < 0) {
2131 				send_resp(dut, conn, SIGMA_ERROR,
2132 					  "errorCode,Failed to parse URI");
2133 				goto out;
2134 			}
2135 		} else if (mutual && action_type &&
2136 			   strcasecmp(action_type, "ManualDPP") == 0) {
2137 			res = get_wpa_cli_events(dut, ctrl, auth_events,
2138 						 buf, sizeof(buf));
2139 			if (res < 0) {
2140 				send_resp(dut, conn, SIGMA_COMPLETE,
2141 					  "BootstrapResult,OK,AuthResult,Timeout");
2142 				goto out;
2143 			}
2144 			sigma_dut_print(dut, DUT_MSG_DEBUG,
2145 					"DPP auth result: %s", buf);
2146 			if (strstr(buf, "DPP-NOT-COMPATIBLE")) {
2147 			    send_resp(dut, conn, SIGMA_COMPLETE,
2148 				      "BootstrapResult,OK,AuthResult,ROLES_NOT_COMPATIBLE");
2149 			    goto out;
2150 			}
2151 
2152 			if (strstr(buf, "DPP-SCAN-PEER-QR-CODE") == NULL) {
2153 				send_resp(dut, conn, SIGMA_ERROR,
2154 					  "errorCode,No scan request for peer QR Code seen");
2155 				goto out;
2156 			}
2157 
2158 			if (dpp_scan_peer_qrcode(dut) < 0) {
2159 				send_resp(dut, conn, SIGMA_ERROR,
2160 					  "errorCode,Failed to scan peer QR Code");
2161 				goto out;
2162 			}
2163 
2164 			snprintf(buf, sizeof(buf), "DPP_QR_CODE %s",
2165 				 dut->dpp_peer_uri);
2166 			if (wpa_command_resp(ifname, buf, buf,
2167 					     sizeof(buf)) < 0) {
2168 				send_resp(dut, conn, SIGMA_ERROR,
2169 					  "errorCode,Failed to parse URI");
2170 				goto out;
2171 			}
2172 		}
2173 	} else {
2174 		send_resp(dut, conn, SIGMA_ERROR,
2175 			  "errorCode,Unknown DPPAuthRole");
2176 		goto out;
2177 	}
2178 
2179 	if (step && strcasecmp(step, "Timeout") == 0) {
2180 		result = "errorCode,Unexpected state";
2181 
2182 		if (strcasecmp(frametype, "PKEXExchangeResponse") == 0) {
2183 			if (dpp_wait_rx(dut, ctrl, 8, -1) < 0)
2184 				result = "BootstrapResult,Timeout";
2185 			else
2186 				result = "BootstrapResult,Errorsent";
2187 		}
2188 
2189 		if (strcasecmp(frametype, "PKEXCRRequest") == 0) {
2190 			if (dpp_wait_rx(dut, ctrl, 9, -1) < 0)
2191 				result = "BootstrapResult,Timeout";
2192 			else
2193 				result = "BootstrapResult,Errorsent";
2194 		}
2195 
2196 		if (strcasecmp(frametype, "PKEXCRResponse") == 0) {
2197 			if (dpp_wait_rx(dut, ctrl, 10, -1) < 0)
2198 				result = "BootstrapResult,Timeout";
2199 			else
2200 				result = "BootstrapResult,Errorsent";
2201 		}
2202 
2203 		if (strcasecmp(frametype, "AuthenticationRequest") == 0) {
2204 			if (dpp_wait_rx(dut, ctrl, 0, -1) < 0)
2205 				result = "BootstrapResult,OK,AuthResult,Timeout";
2206 			else
2207 				result = "BootstrapResult,OK,AuthResult,Errorsent";
2208 		}
2209 
2210 		if (strcasecmp(frametype, "AuthenticationResponse") == 0) {
2211 			if (dpp_wait_rx(dut, ctrl, 1, -1) < 0)
2212 				result = "BootstrapResult,OK,AuthResult,Timeout";
2213 			else
2214 				result = "BootstrapResult,OK,AuthResult,Errorsent";
2215 		}
2216 
2217 		if (strcasecmp(frametype, "AuthenticationConfirm") == 0) {
2218 			if (auth_role &&
2219 			    strcasecmp(auth_role, "Initiator") == 0) {
2220 				/* This special case of DPPStep,Timeout with
2221 				 * DPPFrameType,AuthenticationConfirm on an
2222 				 * Initiator is used to cover need for stopping
2223 				 * the Initiator/Enrollee from sending out
2224 				 * Configuration Request message. */
2225 				if (strcasecmp(prov_role, "Enrollee") != 0) {
2226 					send_resp(dut, conn, SIGMA_ERROR,
2227 						  "errorCode,Unexpected use of timeout after AuthenticationConfirm TX in Configurator role");
2228 					goto out;
2229 				}
2230 				if (check_mutual &&
2231 				    dpp_process_auth_response(
2232 					    dut, conn, ctrl, auth_events,
2233 					    action_type, check_mutual,
2234 					    buf, sizeof(buf)) < 0)
2235 					goto out;
2236 				if (dpp_wait_tx_status(dut, ctrl, 2) < 0)
2237 					result = "BootstrapResult,OK,AuthResult,Timeout";
2238 				else
2239 					result = "BootstrapResult,OK,AuthResult,Errorsent,LastFrameReceived,AuthenticationResponse";
2240 			} else {
2241 				if (dpp_wait_rx(dut, ctrl, 2, -1) < 0)
2242 					result = "BootstrapResult,OK,AuthResult,Timeout";
2243 				else
2244 					result = "BootstrapResult,OK,AuthResult,Errorsent,LastFrameReceived,AuthenticationConfirm";
2245 			}
2246 		}
2247 
2248 		if (strcasecmp(frametype, "ConfigurationRequest") == 0) {
2249 			if (get_wpa_cli_event(dut, ctrl, "DPP-CONF-FAILED",
2250 					      buf, sizeof(buf)) < 0)
2251 				result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Timeout";
2252 			else
2253 				result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Errorsent";
2254 		}
2255 
2256 		send_resp(dut, conn, SIGMA_COMPLETE, result);
2257 		goto out;
2258 	}
2259 
2260 	if (frametype && strcasecmp(frametype, "PKEXExchangeRequest") == 0) {
2261 		if (dpp_wait_tx_status(dut, ctrl, 7) < 0)
2262 			result = "BootstrapResult,Timeout";
2263 		else
2264 			result = "BootstrapResult,Errorsent";
2265 		send_resp(dut, conn, SIGMA_COMPLETE, result);
2266 		goto out;
2267 	}
2268 
2269 	if (frametype && strcasecmp(frametype, "PKEXExchangeResponse") == 0) {
2270 		if (dpp_wait_tx_status(dut, ctrl, 8) < 0)
2271 			result = "BootstrapResult,Timeout";
2272 		else
2273 			result = "BootstrapResult,Errorsent";
2274 		send_resp(dut, conn, SIGMA_COMPLETE, result);
2275 		goto out;
2276 	}
2277 
2278 	if (frametype && strcasecmp(frametype, "PKEXCRRequest") == 0) {
2279 		if (dpp_wait_tx_status(dut, ctrl, 9) < 0)
2280 			result = "BootstrapResult,Timeout";
2281 		else
2282 			result = "BootstrapResult,Errorsent";
2283 		send_resp(dut, conn, SIGMA_COMPLETE, result);
2284 		goto out;
2285 	}
2286 
2287 	if (frametype && strcasecmp(frametype, "PKEXCRResponse") == 0) {
2288 		if (dpp_wait_tx_status(dut, ctrl, 10) < 0)
2289 			result = "BootstrapResult,Timeout";
2290 		else
2291 			result = "BootstrapResult,Errorsent";
2292 		send_resp(dut, conn, SIGMA_COMPLETE, result);
2293 		goto out;
2294 	}
2295 
2296 	if (!frametype && strcasecmp(bs, "PKEX") == 0 &&
2297 	    auth_role && strcasecmp(auth_role, "Responder") == 0) {
2298 		if (dpp_wait_tx_status(dut, ctrl, 10) < 0) {
2299 			send_resp(dut, conn, SIGMA_COMPLETE,
2300 				  "BootstrapResult,Timeout");
2301 			goto out;
2302 		}
2303 	}
2304 
2305 	if (!frametype && strcasecmp(bs, "PKEX") == 0 &&
2306 	    auth_role && strcasecmp(auth_role, "Initiator") == 0) {
2307 		if (dpp_wait_tx(dut, ctrl, 0) < 0) {
2308 			send_resp(dut, conn, SIGMA_COMPLETE,
2309 				  "BootstrapResult,Timeout");
2310 			goto out;
2311 		}
2312 	}
2313 
2314 	if (frametype && strcasecmp(frametype, "AuthenticationRequest") == 0) {
2315 		if (dpp_wait_tx_status(dut, ctrl, 0) < 0) {
2316 			send_resp(dut, conn, SIGMA_COMPLETE,
2317 				  "BootstrapResult,OK,AuthResult,Timeout");
2318 			goto out;
2319 		}
2320 
2321 		if (dpp_wait_rx(dut, ctrl, 1, 5) < 0)
2322 			result = "BootstrapResult,OK,AuthResult,Errorsent,LastFrameReceived,None";
2323 		else if	(get_wpa_cli_events(dut, ctrl, auth_events,
2324 					    buf, sizeof(buf)) >= 0 &&
2325 			 strstr(buf, "DPP-RESPONSE-PENDING") != NULL)
2326 			result = "BootstrapResult,OK,AuthResult,Errorsent,LastFrameReceived,AuthenticationResponseWithStatusPending";
2327 		else
2328 			result = "BootstrapResult,OK,AuthResult,Errorsent,LastFrameReceived,AuthenticationResponse";
2329 		send_resp(dut, conn, SIGMA_COMPLETE, result);
2330 		goto out;
2331 	}
2332 
2333 	if (frametype && strcasecmp(frametype, "AuthenticationResponse") == 0) {
2334 		if (dpp_wait_tx_status(dut, ctrl, 1) < 0) {
2335 			send_resp(dut, conn, SIGMA_COMPLETE,
2336 				  "BootstrapResult,OK,AuthResult,Timeout");
2337 			goto out;
2338 		}
2339 
2340 		if (dpp_wait_rx(dut, ctrl, 2, 5) < 0)
2341 			result = "BootstrapResult,OK,AuthResult,Errorsent,LastFrameReceived,AuthenticationRequest";
2342 		else
2343 			result = "BootstrapResult,OK,AuthResult,Errorsent,LastFrameReceived,AuthenticationConfirm";
2344 		send_resp(dut, conn, SIGMA_COMPLETE, result);
2345 		goto out;
2346 	}
2347 
2348 	if (dpp_process_auth_response(dut, conn, ctrl, auth_events, action_type,
2349 				      check_mutual, buf, sizeof(buf)) < 0)
2350 		goto out;
2351 
2352 	if (frametype && strcasecmp(frametype, "AuthenticationConfirm") == 0) {
2353 		if (dpp_wait_tx_status(dut, ctrl, 2) < 0) {
2354 			send_resp(dut, conn, SIGMA_COMPLETE,
2355 				  "BootstrapResult,OK,AuthResult,Timeout");
2356 			goto out;
2357 		}
2358 
2359 		if (dpp_wait_rx_conf_req(dut, ctrl, 5) < 0)
2360 			result = "BootstrapResult,OK,AuthResult,Errorsent,LastFrameReceived,AuthenticationResponse";
2361 		else
2362 			result = "BootstrapResult,OK,AuthResult,Errorsent,LastFrameReceived,ConfigurationRequest";
2363 		send_resp(dut, conn, SIGMA_COMPLETE, result);
2364 		goto out;
2365 	}
2366 
2367 	if (strstr(buf, "DPP-AUTH-DIRECTION")) {
2368 		res = get_wpa_cli_events(dut, ctrl, auth_events,
2369 					 buf, sizeof(buf));
2370 		if (res < 0) {
2371 			send_resp(dut, conn, SIGMA_COMPLETE,
2372 				  "BootstrapResult,OK,AuthResult,Timeout");
2373 			goto out;
2374 		}
2375 
2376 		sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP auth result: %s", buf);
2377 	}
2378 
2379 	if (strstr(buf, "DPP-NOT-COMPATIBLE")) {
2380 		send_resp(dut, conn, SIGMA_COMPLETE,
2381 			  "BootstrapResult,OK,AuthResult,ROLES_NOT_COMPATIBLE");
2382 		goto out;
2383 	}
2384 
2385 	if (!strstr(buf, "DPP-AUTH-SUCCESS")) {
2386 		send_resp(dut, conn, SIGMA_COMPLETE,
2387 			  "BootstrapResult,OK,AuthResult,FAILED");
2388 		goto out;
2389 	}
2390 
2391 	if (frametype && strcasecmp(frametype, "ConfigurationRequest") == 0) {
2392 		res = get_wpa_cli_event(dut, ctrl, "GAS-QUERY-DONE",
2393 					buf, sizeof(buf));
2394 		if (res < 0)
2395 			result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Timeout";
2396 		else
2397 			result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Errorsent";
2398 		send_resp(dut, conn, SIGMA_COMPLETE, result);
2399 		goto out;
2400 	}
2401 
2402 	if (frametype && strcasecmp(frametype, "ConfigurationResponse") == 0) {
2403 		res = get_wpa_cli_events(dut, ctrl, conf_events,
2404 					 buf, sizeof(buf));
2405 		if (res >= 0 && strstr(buf, "DPP-MUD-URL "))
2406 			res = get_wpa_cli_events(dut, ctrl, conf_events,
2407 						 buf, sizeof(buf));
2408 		if (res < 0)
2409 			result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Timeout";
2410 		else
2411 			result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Errorsent,LastFrameReceived,ConfigurationRequest";
2412 		send_resp(dut, conn, SIGMA_COMPLETE, result);
2413 		goto out;
2414 	}
2415 
2416 	if (strcasecmp(prov_role, "Configurator") == 0 && csrattrs[0]) {
2417 		res = get_wpa_cli_event(dut, ctrl, "DPP-CSR", buf, sizeof(buf));
2418 		if (res < 0) {
2419 			send_resp(dut, conn, SIGMA_ERROR,
2420 				  "errorCode,No CSR received from Enrollee");
2421 			res = STATUS_SENT_ERROR;
2422 			goto out;
2423 		}
2424 
2425 		if (dpp_process_csr(dut, ifname, buf) < 0) {
2426 			send_resp(dut, conn, SIGMA_ERROR,
2427 				  "errorCode,Failed to process CSR");
2428 			res = STATUS_SENT_ERROR;
2429 			goto out;
2430 		}
2431 	}
2432 
2433 	res = get_wpa_cli_events(dut, ctrl, conf_events, buf, sizeof(buf));
2434 	if (res >= 0 && strstr(buf, "DPP-MUD-URL ")) {
2435 		size_t url_len;
2436 
2437 		pos = strchr(buf, ' ');
2438 		if (!pos)
2439 			goto err;
2440 		pos++;
2441 		url_len = strlen(buf);
2442 		mud_url = malloc(9 + url_len);
2443 		if (!mud_url)
2444 			goto err;
2445 		memcpy(mud_url, ",MUDURL,", 8);
2446 		memcpy(mud_url + 8, pos, url_len + 1);
2447 
2448 		res = get_wpa_cli_events(dut, ctrl, conf_events,
2449 					 buf, sizeof(buf));
2450 	}
2451 	if (res < 0) {
2452 		send_resp(dut, conn, SIGMA_COMPLETE,
2453 			  "BootstrapResult,OK,AuthResult,OK,ConfResult,Timeout");
2454 		goto out;
2455 	}
2456 	sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP conf result: %s", buf);
2457 
2458 	if (!strstr(buf, "DPP-CONF-SENT") &&
2459 	    !strstr(buf, "DPP-CONF-RECEIVED")) {
2460 		send_resp(dut, conn, SIGMA_COMPLETE,
2461 			  "BootstrapResult,OK,AuthResult,OK,ConfResult,FAILED");
2462 		goto out;
2463 	}
2464 
2465 	if (conn_status && strstr(buf, "DPP-CONF-SENT") &&
2466 	    strstr(buf, "wait_conn_status=1")) {
2467 		res = get_wpa_cli_event(dut, ctrl, "DPP-CONN-STATUS-RESULT",
2468 					buf, sizeof(buf));
2469 		if (res < 0) {
2470 			send_resp(dut, conn, SIGMA_COMPLETE,
2471 				  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,StatusResult,Timeout");
2472 		} else {
2473 			pos = strstr(buf, "result=");
2474 			if (!pos) {
2475 				send_resp(dut, conn, SIGMA_ERROR,
2476 					  "errorCode,Status result value not reported");
2477 			} else {
2478 				pos += 7;
2479 				snprintf(buf, sizeof(buf),
2480 					 "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,StatusResult,%d%s",
2481 					 atoi(pos), mud_url);
2482 				send_resp(dut, conn, SIGMA_COMPLETE, buf);
2483 			}
2484 		}
2485 		goto out;
2486 	}
2487 
2488 	if (strcasecmp(prov_role, "Enrollee") == 0 && netrole &&
2489 	    strcmp(netrole, "configurator") == 0) {
2490 		res = get_wpa_cli_event(dut, ctrl, "DPP-CONFIGURATOR-ID",
2491 					buf, sizeof(buf));
2492 		if (res < 0) {
2493 			send_resp(dut, conn, SIGMA_ERROR,
2494 				  "errorCode,No DPP-CONFIGURATOR-ID");
2495 			goto out;
2496 		}
2497 		pos = strchr(buf, ' ');
2498 		if (!pos) {
2499 			send_resp(dut, conn, SIGMA_ERROR,
2500 				  "errorCode,Invalid DPP-CONFIGURATOR-ID");
2501 			goto out;
2502 		}
2503 		pos++;
2504 		dut->dpp_conf_id = atoi(pos);
2505 	} else if (sigma_dut_is_ap(dut) &&
2506 		   strcasecmp(prov_role, "Enrollee") == 0) {
2507 	update_ap:
2508 		res = dpp_hostapd_conf_update(dut, conn, ifname, ctrl);
2509 		if (res == 0)
2510 			goto out;
2511 		if (res < 0) {
2512 			send_resp(dut, conn, SIGMA_ERROR, NULL);
2513 			goto out;
2514 		}
2515 	}
2516 
2517 	if (strcasecmp(wait_conn, "Yes") == 0 &&
2518 	    !sigma_dut_is_ap(dut) &&
2519 	    strcasecmp(prov_role, "Enrollee") == 0) {
2520 		int netw_id;
2521 		char *pos;
2522 
2523 		res = get_wpa_cli_event(dut, ctrl, "DPP-NETWORK-ID",
2524 					buf, sizeof(buf));
2525 		if (res < 0) {
2526 			send_resp(dut, conn, SIGMA_ERROR,
2527 				  "errorCode,No DPP-NETWORK-ID");
2528 			goto out;
2529 		}
2530 		pos = strchr(buf, ' ');
2531 		if (!pos) {
2532 			send_resp(dut, conn, SIGMA_ERROR,
2533 				  "errorCode,Invalid DPP-NETWORK-ID");
2534 			goto out;
2535 		}
2536 		pos++;
2537 		netw_id = atoi(pos);
2538 		snprintf(buf, sizeof(buf), "GET_NETWORK %d key_mgmt", netw_id);
2539 		if (wpa_command_resp(ifname, buf, buf, sizeof(buf)) < 0) {
2540 			send_resp(dut, conn, SIGMA_ERROR,
2541 				  "errorCode,Could not fetch provisioned key_mgmt");
2542 			goto out;
2543 		}
2544 		if (strncmp(buf, "SAE", 3) == 0) {
2545 			/* SAE generates PMKSA-CACHE-ADDED event */
2546 			not_dpp_akm = 1;
2547 		}
2548 		dut->dpp_network_id = netw_id;
2549 	wait_connect:
2550 		if (frametype && strcasecmp(frametype,
2551 					    "PeerDiscoveryRequest") == 0) {
2552 			if (dpp_wait_tx_status(dut, ctrl, 5) < 0)
2553 				result = "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Timeout";
2554 			else
2555 				result = "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Errorsent";
2556 			send_resp(dut, conn, SIGMA_COMPLETE, result);
2557 			goto out;
2558 		}
2559 
2560 		res = get_wpa_cli_events(dut, ctrl, conn_events,
2561 					 buf, sizeof(buf));
2562 		if (res < 0) {
2563 			send_resp(dut, conn, SIGMA_COMPLETE,
2564 				  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Timeout,NetworkConnectResult,Timeout");
2565 			goto out;
2566 		}
2567 		sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP connect result: %s",
2568 				buf);
2569 
2570 		if (strstr(buf, "PMKSA-CACHE-ADDED")) {
2571 			res = get_wpa_cli_events(dut, ctrl, conn_events,
2572 						 buf, sizeof(buf));
2573 			if (res < 0) {
2574 				send_resp(dut, conn, SIGMA_COMPLETE,
2575 					  not_dpp_akm ?
2576 					  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkConnectResult,Timeout" :
2577 					  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,OK,NetworkConnectResult,Timeout");
2578 				goto out;
2579 			}
2580 			sigma_dut_print(dut, DUT_MSG_DEBUG,
2581 					"DPP connect result: %s", buf);
2582 			if (strstr(buf, "CTRL-EVENT-CONNECTED"))
2583 				send_resp(dut, conn, SIGMA_COMPLETE,
2584 					  not_dpp_akm ?
2585 					  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkConnectResult,OK" :
2586 					  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,OK,NetworkConnectResult,OK");
2587 			else
2588 				send_resp(dut, conn, SIGMA_COMPLETE,
2589 					  not_dpp_akm ?
2590 					  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkConnectResult,Timeout" :
2591 					  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,OK,NetworkConnectResult,Timeout");
2592 			goto out;
2593 		}
2594 
2595 		send_resp(dut, conn, SIGMA_COMPLETE,
2596 			  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkConnectResult,OK");
2597 		goto out;
2598 	} else if (!sigma_dut_is_ap(dut) &&
2599 		   strcasecmp(prov_role, "Enrollee") == 0) {
2600 		/* Store DPP network id for reconfiguration */
2601 		char *pos;
2602 		unsigned int old_timeout;
2603 
2604 		old_timeout = dut->default_timeout;
2605 		dut->default_timeout = 3;
2606 		res = get_wpa_cli_event(dut, ctrl, "DPP-NETWORK-ID",
2607 					buf, sizeof(buf));
2608 		dut->default_timeout = old_timeout;
2609 
2610 		if (res < 0) {
2611 			sigma_dut_print(dut, DUT_MSG_INFO, "No DPP-NETWORK-ID");
2612 		} else {
2613 			pos = strchr(buf, ' ');
2614 			if (!pos) {
2615 				sigma_dut_print(dut, DUT_MSG_INFO,
2616 						"Invalid DPP-NETWORK-ID");
2617 			} else {
2618 				pos++;
2619 				dut->dpp_network_id = atoi(pos);
2620 			}
2621 		}
2622 	}
2623 
2624 	if (strcasecmp(wait_conn, "Yes") == 0 &&
2625 	    frametype && strcasecmp(frametype, "PeerDiscoveryResponse") == 0) {
2626 		if (dpp_wait_tx_status(dut, ctrl, 6) < 0)
2627 			result = "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Timeout";
2628 		else
2629 			result = "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Errorsent";
2630 		send_resp(dut, conn, SIGMA_COMPLETE, result);
2631 		goto out;
2632 	}
2633 
2634 	snprintf(buf, sizeof(buf),
2635 		 "BootstrapResult,OK,AuthResult,OK,ConfResult,OK%s", mud_url);
2636 	send_resp(dut, conn, SIGMA_COMPLETE, buf);
2637 out:
2638 	if (mud_url != no_mud_url)
2639 		free(mud_url);
2640 	wpa_ctrl_detach(ctrl);
2641 	wpa_ctrl_close(ctrl);
2642 	if (tcp && strcasecmp(tcp, "yes") == 0 &&
2643 	    auth_role && strcasecmp(auth_role, "Responder") == 0)
2644 		wpa_command(ifname, "DPP_CONTROLLER_STOP");
2645 	dut->default_timeout = old_timeout;
2646 	return STATUS_SENT;
2647 err:
2648 	send_resp(dut, conn, SIGMA_ERROR, NULL);
2649 	goto out;
2650 }
2651 
2652 
2653 static enum sigma_cmd_result dpp_manual_dpp(struct sigma_dut *dut,
2654 					    struct sigma_conn *conn,
2655 					    struct sigma_cmd *cmd)
2656 {
2657 	const char *auth_role = get_param(cmd, "DPPAuthRole");
2658 	const char *self_conf = get_param(cmd, "DPPSelfConfigure");
2659 	enum sigma_cmd_result res = INVALID_SEND_STATUS;
2660 	int success;
2661 	const char *val;
2662 	unsigned int old_timeout;
2663 	const char *bs = get_param(cmd, "DPPBS");
2664 
2665 	if (!self_conf)
2666 		self_conf = "no";
2667 
2668 	old_timeout = dut->default_timeout;
2669 	val = get_param(cmd, "DPPTimeout");
2670 	if (val && atoi(val) > 0) {
2671 		dut->default_timeout = atoi(val);
2672 		sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP timeout: %u",
2673 				dut->default_timeout);
2674 	}
2675 
2676 	if (strcasecmp(bs, "NFC") == 0) {
2677 		res = dpp_automatic_dpp(dut, conn, cmd);
2678 		goto out;
2679 	}
2680 
2681 	res = dpp_get_local_bootstrap(dut, conn, cmd, 0, &success);
2682 	if (res != STATUS_SENT || !success)
2683 		goto out;
2684 
2685 	if (!auth_role) {
2686 		send_resp(dut, conn, SIGMA_ERROR,
2687 			  "errorCode,Missing DPPAuthRole");
2688 		return STATUS_SENT_ERROR;
2689 	}
2690 
2691 	if (strcasecmp(auth_role, "Responder") == 0) {
2692 		if (dpp_display_own_qrcode(dut) < 0) {
2693 			send_resp(dut, conn, SIGMA_ERROR,
2694 				  "errorCode,Failed to display own QR code");
2695 			res = STATUS_SENT_ERROR;
2696 			goto out;
2697 		}
2698 
2699 		res = dpp_automatic_dpp(dut, conn, cmd);
2700 		goto out;
2701 	}
2702 
2703 	if (strcasecmp(auth_role, "Initiator") == 0) {
2704 		if (strcasecmp(self_conf, "Yes") != 0) {
2705 			if (dpp_scan_peer_qrcode(dut) < 0) {
2706 				send_resp(dut, conn, SIGMA_ERROR,
2707 					  "errorCode,Failed to scan peer QR Code");
2708 				res = STATUS_SENT_ERROR;
2709 				goto out;
2710 			}
2711 		}
2712 
2713 		res = dpp_automatic_dpp(dut, conn, cmd);
2714 		goto out;
2715 	}
2716 
2717 	send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unknown DPPAuthRole");
2718 	res = STATUS_SENT_ERROR;
2719 out:
2720 	dut->default_timeout = old_timeout;
2721 	return res;
2722 }
2723 
2724 
2725 static enum sigma_cmd_result
2726 dpp_reconfigure_configurator(struct sigma_dut *dut, struct sigma_conn *conn,
2727 			     struct sigma_cmd *cmd)
2728 {
2729 	const char *val;
2730 	int freq;
2731 	struct wpa_ctrl *ctrl = NULL;
2732 	const char *ifname;
2733 	int conf_index;
2734 	const char *conf_role;
2735 	const char *group_id_str = NULL;
2736 	char *pos;
2737 	char buf[2000];
2738 	char buf2[200];
2739 	char conf_ssid[100];
2740 	char conf_pass[100];
2741 	char csrattrs[200];
2742 	char group_id[100];
2743 	char conf2[300];
2744 	FILE *f;
2745 	int enrollee_ap = 0;
2746 	int force_gas_fragm = 0;
2747 	int akm_use_selector = 0;
2748 	int conn_status;
2749 	int res;
2750 	const char *conf_events[] = {
2751 		"DPP-CONF-SENT",
2752 		"DPP-CONF-FAILED",
2753 		NULL
2754 	};
2755 
2756 	if (sigma_dut_is_ap(dut)) {
2757 		if (!dut->hostapd_ifname) {
2758 			sigma_dut_print(dut, DUT_MSG_ERROR,
2759 					"hostapd ifname not specified (-j)");
2760 			return ERROR_SEND_STATUS;
2761 		}
2762 		ifname = dut->hostapd_ifname;
2763 	} else {
2764 		ifname = get_station_ifname(dut);
2765 	}
2766 
2767 	val = get_param(cmd, "DPPConfEnrolleeRole");
2768 	if (val)
2769 		enrollee_ap = strcasecmp(val, "AP") == 0;
2770 
2771 	val = get_param(cmd, "DPPStatusQuery");
2772 	conn_status = val && strcasecmp(val, "Yes") == 0;
2773 
2774 	conf_ssid[0] = '\0';
2775 	conf_pass[0] = '\0';
2776 	csrattrs[0] = '\0';
2777 	group_id[0] = '\0';
2778 	conf2[0] = '\0';
2779 
2780 	val = get_param(cmd, "DPPConfIndex");
2781 	if (!val) {
2782 		sigma_dut_print(dut, DUT_MSG_ERROR,
2783 				"DPPConfIndex not specified for Configurator");
2784 		return ERROR_SEND_STATUS;
2785 	}
2786 	conf_index = atoi(val);
2787 
2788 	switch (conf_index) {
2789 	case 1:
2790 		ascii2hexstr("DPPNET01", buf);
2791 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
2792 		if (res < 0 || res >= sizeof(conf_ssid))
2793 			goto err;
2794 		if (enrollee_ap) {
2795 			conf_role = "ap-dpp";
2796 		} else {
2797 			conf_role = "sta-dpp";
2798 		}
2799 		group_id_str = "DPPGROUP_DPP_INFRA";
2800 		break;
2801 	case 2:
2802 		ascii2hexstr("DPPNET01", buf);
2803 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
2804 		if (res < 0 || res >= sizeof(conf_ssid))
2805 			goto err;
2806 		snprintf(conf_pass, sizeof(conf_pass),
2807 			 "psk=10506e102ad1e7f95112f6b127675bb8344dacacea60403f3fa4055aec85b0fc");
2808 		if (enrollee_ap)
2809 			conf_role = "ap-psk";
2810 		else
2811 			conf_role = "sta-psk";
2812 		break;
2813 	case 3:
2814 		ascii2hexstr("DPPNET01", buf);
2815 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
2816 		if (res < 0 || res >= sizeof(conf_ssid))
2817 			goto err;
2818 		ascii2hexstr("ThisIsDppPassphrase", buf);
2819 		res = snprintf(conf_pass, sizeof(conf_pass), "pass=%s", buf);
2820 		if (res < 0 || res >= sizeof(conf_pass))
2821 			goto err;
2822 		if (enrollee_ap)
2823 			conf_role = "ap-psk";
2824 		else
2825 			conf_role = "sta-psk";
2826 		break;
2827 	case 4:
2828 		ascii2hexstr("DPPNET01", buf);
2829 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
2830 		if (res < 0 || res >= sizeof(conf_ssid))
2831 			goto err;
2832 		if (enrollee_ap) {
2833 			conf_role = "ap-dpp";
2834 		} else {
2835 			conf_role = "sta-dpp";
2836 		}
2837 		group_id_str = "DPPGROUP_DPP_INFRA2";
2838 		break;
2839 	case 5:
2840 		ascii2hexstr("DPPNET01", buf);
2841 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
2842 		if (res < 0 || res >= sizeof(conf_ssid))
2843 			goto err;
2844 		ascii2hexstr("ThisIsDppPassphrase", buf);
2845 		res = snprintf(conf_pass, sizeof(conf_pass), "pass=%s", buf);
2846 		if (res < 0 || res >= sizeof(conf_pass))
2847 			goto err;
2848 		if (enrollee_ap)
2849 			conf_role = "ap-sae";
2850 		else
2851 			conf_role = "sta-sae";
2852 		break;
2853 	case 6:
2854 		ascii2hexstr("DPPNET01", buf);
2855 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
2856 		if (res < 0 || res >= sizeof(conf_ssid))
2857 			goto err;
2858 		ascii2hexstr("ThisIsDppPassphrase", buf);
2859 		res = snprintf(conf_pass, sizeof(conf_pass), "pass=%s", buf);
2860 		if (res < 0 || res >= sizeof(conf_pass))
2861 			goto err;
2862 		if (enrollee_ap)
2863 			conf_role = "ap-psk-sae";
2864 		else
2865 			conf_role = "sta-psk-sae";
2866 		break;
2867 	case 7:
2868 		ascii2hexstr("DPPNET01", buf);
2869 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
2870 		if (res < 0 || res >= sizeof(conf_ssid))
2871 			goto err;
2872 		if (enrollee_ap) {
2873 			conf_role = "ap-dpp";
2874 		} else {
2875 			conf_role = "sta-dpp";
2876 		}
2877 		group_id_str = "DPPGROUP_DPP_INFRA";
2878 		force_gas_fragm = 1;
2879 		break;
2880 	case 8:
2881 	case 9:
2882 		ascii2hexstr("DPPNET01", buf);
2883 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
2884 		if (res < 0 || res >= sizeof(conf_ssid))
2885 			goto err;
2886 		ascii2hexstr("This_is_legacy_password", buf);
2887 		res = snprintf(conf_pass, sizeof(conf_pass), "pass=%s", buf);
2888 		if (res < 0 || res >= sizeof(conf_pass))
2889 			goto err;
2890 		if (enrollee_ap) {
2891 			conf_role = "ap-dpp+psk+sae";
2892 		} else {
2893 			conf_role = "sta-dpp+psk+sae";
2894 		}
2895 		group_id_str = "DPPGROUP_DPP_INFRA1";
2896 		if (conf_index == 9)
2897 			akm_use_selector = 1;
2898 		break;
2899 	case 10:
2900 		ascii2hexstr("DPPNET01", buf);
2901 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
2902 		if (res < 0 || res >= sizeof(conf_ssid))
2903 			goto err;
2904 		if (enrollee_ap)
2905 			conf_role = "ap-dpp";
2906 		else
2907 			conf_role = "sta-dpp";
2908 		group_id_str = "DPPGROUP_DPP_INFRA1";
2909 		ascii2hexstr("DPPNET02", buf);
2910 		ascii2hexstr("This_is_legacy_password", buf2);
2911 		res = snprintf(conf2, sizeof(conf2),
2912 			       " @CONF-OBJ-SEP@ conf=%s-dpp+psk+sae ssid=%s pass=%s group_id=DPPGROUP_DPP_INFRA2",
2913 			       enrollee_ap ? "ap" : "sta", buf, buf2);
2914 		if (res < 0 || res >= sizeof(conf2))
2915 			goto err;
2916 		break;
2917 	case 11:
2918 		ascii2hexstr("DPPNET01", buf);
2919 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
2920 		if (res < 0 || res >= sizeof(conf_ssid))
2921 			goto err;
2922 		if (enrollee_ap) {
2923 			send_resp(dut, conn, SIGMA_ERROR,
2924 				  "errorCode,dot1x AKM provisioning not supported for AP");
2925 			goto out;
2926 		}
2927 		conf_role = "sta-dot1x";
2928 		snprintf(buf, sizeof(buf), "%s/dpp-ca-csrattrs",
2929 			 sigma_cert_path);
2930 		f = fopen(buf, "r");
2931 		if (f) {
2932 			size_t len;
2933 			int r;
2934 
2935 			len = fread(buf, 1, sizeof(buf), f);
2936 			fclose(f);
2937 			if (len >= sizeof(buf)) {
2938 				send_resp(dut, conn, SIGMA_ERROR,
2939 					  "errorCode,No room for csrAttrs");
2940 				goto out;
2941 			}
2942 			buf[len] = '\0';
2943 			sigma_dut_print(dut, DUT_MSG_INFO,
2944 					"Use csrAttrs from file");
2945 			r = snprintf(csrattrs, sizeof(csrattrs),
2946 				     " csrattrs=%s", buf);
2947 			if (r <= 0 || r >= sizeof(csrattrs)) {
2948 				send_resp(dut, conn, SIGMA_ERROR,
2949 					  "errorCode,No room for csrAttrs");
2950 				goto out;
2951 			}
2952 		} else {
2953 			sigma_dut_print(dut, DUT_MSG_INFO,
2954 					"Use default csrAttrs");
2955 			snprintf(csrattrs, sizeof(csrattrs), "%s",
2956 				 " csrattrs=MAsGCSqGSIb3DQEJBw==");
2957 		}
2958 		break;
2959 	default:
2960 		send_resp(dut, conn, SIGMA_ERROR,
2961 			  "errorCode,Unsupported DPPConfIndex");
2962 		goto out;
2963 	}
2964 
2965 	if (group_id_str)
2966 		snprintf(group_id, sizeof(group_id), " group_id=%s",
2967 			 group_id_str);
2968 
2969 	if (force_gas_fragm) {
2970 		char spaces[1500];
2971 
2972 		memset(spaces, ' ', sizeof(spaces));
2973 		spaces[sizeof(spaces) - 1] = '\0';
2974 
2975 		snprintf(buf, sizeof(buf),
2976 			 "SET dpp_discovery_override {\"ssid\":\"DPPNET01\"}%s",
2977 			 spaces);
2978 		if (wpa_command(ifname, buf) < 0) {
2979 			send_resp(dut, conn, SIGMA_ERROR,
2980 				  "errorCode,Failed to set discovery override");
2981 			goto out;
2982 		}
2983 	}
2984 
2985 	snprintf(buf, sizeof(buf),
2986 		 "SET dpp_configurator_params  conf=%s %s %s configurator=%d%s%s%s%s%s",
2987 		 conf_role, conf_ssid, conf_pass,
2988 		 dut->dpp_conf_id, group_id,
2989 		 akm_use_selector ? " akm_use_selector=1" : "",
2990 		 conn_status ? " conn_status=1" : "", csrattrs,
2991 		 conf2);
2992 	if (wpa_command(ifname, buf) < 0) {
2993 		send_resp(dut, conn, SIGMA_ERROR,
2994 			  "errorCode,Failed to set configurator parameters");
2995 		goto out;
2996 	}
2997 
2998 	ctrl = open_wpa_mon(ifname);
2999 	if (!ctrl) {
3000 		sigma_dut_print(dut, DUT_MSG_ERROR,
3001 				"Failed to open wpa_supplicant monitor connection");
3002 		return ERROR_SEND_STATUS;
3003 	}
3004 
3005 	val = get_param(cmd, "DPPListenChannel");
3006 	if (val) {
3007 		freq = channel_to_freq(dut, atoi(val));
3008 		if (freq == 0) {
3009 			send_resp(dut, conn, SIGMA_ERROR,
3010 				  "errorCode,Unsupported DPPListenChannel value");
3011 			goto out;
3012 		}
3013 		snprintf(buf, sizeof(buf),
3014 			 "DPP_LISTEN %d role=configurator", freq);
3015 		if (wpa_command(ifname, buf) < 0) {
3016 			send_resp(dut, conn, SIGMA_ERROR,
3017 				  "errorCode,Could not start listen state");
3018 			goto out;
3019 		}
3020 	}
3021 
3022 	res = get_wpa_cli_event(dut, ctrl, "DPP-CONF-REQ-RX",
3023 				buf, sizeof(buf));
3024 	if (res < 0) {
3025 		send_resp(dut, conn, SIGMA_COMPLETE,
3026 			  "ReconfigAuthResult,Timeout");
3027 		goto out;
3028 	}
3029 
3030 	res = get_wpa_cli_events(dut, ctrl, conf_events, buf, sizeof(buf));
3031 	if (res < 0) {
3032 		send_resp(dut, conn, SIGMA_COMPLETE,
3033 			  "ReconfigAuthResult,OK,ConfResult,Timeout");
3034 		goto out;
3035 	}
3036 	if (!strstr(buf, "DPP-CONF-SENT")) {
3037 		send_resp(dut, conn, SIGMA_COMPLETE,
3038 			  "ReconfigAuthResult,OK,ConfResult,FAILED");
3039 		goto out;
3040 	}
3041 
3042 	if (conn_status && strstr(buf, "wait_conn_status=1")) {
3043 		res = get_wpa_cli_event(dut, ctrl, "DPP-CONN-STATUS-RESULT",
3044 					buf, sizeof(buf));
3045 		if (res < 0) {
3046 			send_resp(dut, conn, SIGMA_COMPLETE,
3047 				  "ReconfigAuthResult,OK,ConfResult,OK,StatusResult,Timeout");
3048 		} else {
3049 			pos = strstr(buf, "result=");
3050 			if (!pos) {
3051 				send_resp(dut, conn, SIGMA_ERROR,
3052 					  "errorCode,Status result value not reported");
3053 			} else {
3054 				pos += 7;
3055 				snprintf(buf, sizeof(buf),
3056 					 "ReconfigAuthResult,OK,ConfResult,OK,StatusResult,%d",
3057 					 atoi(pos));
3058 				send_resp(dut, conn, SIGMA_COMPLETE, buf);
3059 			}
3060 		}
3061 		goto out;
3062 	}
3063 
3064 	send_resp(dut, conn, SIGMA_COMPLETE,
3065 		  "ReconfigAuthResult,OK,ConfResult,OK");
3066 
3067 out:
3068 	if (ctrl) {
3069 		wpa_ctrl_detach(ctrl);
3070 		wpa_ctrl_close(ctrl);
3071 	}
3072 	return STATUS_SENT;
3073 err:
3074 	send_resp(dut, conn, SIGMA_ERROR, NULL);
3075 	goto out;
3076 }
3077 
3078 
3079 static enum sigma_cmd_result dpp_reconfigure(struct sigma_dut *dut,
3080 					     struct sigma_conn *conn,
3081 					     struct sigma_cmd *cmd)
3082 {
3083 	const char *wait_conn;
3084 	char buf[200];
3085 	const char *ifname;
3086 	struct wpa_ctrl *ctrl;
3087 	const char *conf_events[] = {
3088 		"DPP-CONF-RECEIVED",
3089 		"DPP-CONF-FAILED",
3090 		NULL
3091 	};
3092 	const char *conn_events[] = {
3093 		"PMKSA-CACHE-ADDED",
3094 		"CTRL-EVENT-CONNECTED",
3095 		NULL
3096 	};
3097 	int res;
3098 
3099 	if (get_param(cmd, "DPPConfIndex"))
3100 		return dpp_reconfigure_configurator(dut, conn, cmd);
3101 
3102 	/* Enrollee reconfiguration steps */
3103 	ifname = get_station_ifname(dut);
3104 	wait_conn = get_param(cmd, "DPPWaitForConnect");
3105 	if (!wait_conn)
3106 		wait_conn = "no";
3107 
3108 	ctrl = open_wpa_mon(ifname);
3109 	if (!ctrl) {
3110 		sigma_dut_print(dut, DUT_MSG_ERROR,
3111 				"Failed to open wpa_supplicant monitor connection");
3112 		return ERROR_SEND_STATUS;
3113 	}
3114 
3115 	snprintf(buf, sizeof(buf), "DPP_RECONFIG %d iter=10",
3116 		 dut->dpp_network_id);
3117 	if (wpa_command(ifname, buf) < 0) {
3118 		send_resp(dut, conn, SIGMA_ERROR,
3119 			  "errorCode,Failed to start reconfiguration");
3120 		goto out;
3121 	}
3122 
3123 	res = get_wpa_cli_event(dut, ctrl, "GAS-QUERY-START",
3124 				buf, sizeof(buf));
3125 	if (res < 0) {
3126 		send_resp(dut, conn, SIGMA_COMPLETE,
3127 			  "ReconfigAuthResult,Timeout");
3128 		goto out;
3129 	}
3130 
3131 	res = get_wpa_cli_events(dut, ctrl, conf_events, buf, sizeof(buf));
3132 	if (res < 0) {
3133 		send_resp(dut, conn, SIGMA_COMPLETE,
3134 			  "ReconfigAuthResult,OK,ConfResult,Timeout");
3135 		goto out;
3136 	}
3137 	if (!strstr(buf, "DPP-CONF-RECEIVED")) {
3138 		send_resp(dut, conn, SIGMA_COMPLETE,
3139 			  "ReconfigAuthResult,OK,ConfResult,FAILED");
3140 		goto out;
3141 	}
3142 
3143 	if (strcasecmp(wait_conn, "Yes") == 0) {
3144 		int not_dpp_akm = 0;
3145 
3146 		snprintf(buf, sizeof(buf), "GET_NETWORK %d key_mgmt",
3147 			 dut->dpp_network_id);
3148 		if (wpa_command_resp(ifname, buf, buf, sizeof(buf)) < 0) {
3149 			send_resp(dut, conn, SIGMA_ERROR,
3150 				  "errorCode,Could not fetch provisioned key_mgmt");
3151 			goto out;
3152 		}
3153 		if (strncmp(buf, "SAE", 3) == 0) {
3154 			/* SAE generates PMKSA-CACHE-ADDED event */
3155 			not_dpp_akm = 1;
3156 		}
3157 
3158 		res = get_wpa_cli_events(dut, ctrl, conn_events,
3159 					 buf, sizeof(buf));
3160 		if (res < 0) {
3161 			send_resp(dut, conn, SIGMA_COMPLETE,
3162 				  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Timeout,NetworkConnectResult,Timeout");
3163 			goto out;
3164 		}
3165 		sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP connect result: %s",
3166 				buf);
3167 
3168 		if (strstr(buf, "PMKSA-CACHE-ADDED")) {
3169 			res = get_wpa_cli_events(dut, ctrl, conn_events,
3170 						 buf, sizeof(buf));
3171 			if (res < 0) {
3172 				send_resp(dut, conn, SIGMA_COMPLETE,
3173 					  not_dpp_akm ?
3174 					  "ReconfigAuthResult,OK,ConfResult,OK,NetworkConnectResult,Timeout" :
3175 					  "ReconfigAuthResult,OK,ConfResult,OK,NetworkIntroResult,OK,NetworkConnectResult,Timeout");
3176 				goto out;
3177 			}
3178 			sigma_dut_print(dut, DUT_MSG_DEBUG,
3179 					"DPP connect result: %s", buf);
3180 			if (strstr(buf, "CTRL-EVENT-CONNECTED"))
3181 				send_resp(dut, conn, SIGMA_COMPLETE,
3182 					  not_dpp_akm ?
3183 					  "ReconfigAuthResult,OK,ConfResult,OK,NetworkConnectResult,OK" :
3184 					  "ReconfigAuthResult,OK,ConfResult,OK,NetworkIntroResult,OK,NetworkConnectResult,OK");
3185 			else
3186 				send_resp(dut, conn, SIGMA_COMPLETE,
3187 					  not_dpp_akm ?
3188 					  "ReconfigAuthResult,OK,ConfResult,OK,NetworkConnectResult,Timeout" :
3189 					  "ReconfigAuthResult,OK,ConfResult,OK,NetworkIntroResult,OK,NetworkConnectResult,Timeout");
3190 			goto out;
3191 		}
3192 
3193 		send_resp(dut, conn, SIGMA_COMPLETE,
3194 			  "ReconfigAuthResult,OK,ConfResult,OK,NetworkConnectResult,OK");
3195 		goto out;
3196 	}
3197 
3198 	send_resp(dut, conn, SIGMA_COMPLETE,
3199 		  "ReconfigAuthResult,OK,ConfResult,OK");
3200 
3201 out:
3202 	wpa_ctrl_detach(ctrl);
3203 	wpa_ctrl_close(ctrl);
3204 	return STATUS_SENT;
3205 }
3206 
3207 
3208 enum sigma_cmd_result dpp_dev_exec_action(struct sigma_dut *dut,
3209 					  struct sigma_conn *conn,
3210 					  struct sigma_cmd *cmd)
3211 {
3212 	const char *type = get_param(cmd, "DPPActionType");
3213 	const char *bs = get_param(cmd, "DPPBS");
3214 
3215 	if (!type) {
3216 		send_resp(dut, conn, SIGMA_ERROR,
3217 			  "errorCode,Missing DPPActionType");
3218 		return STATUS_SENT_ERROR;
3219 	}
3220 
3221 	if (strcasecmp(type, "DPPReconfigure") == 0)
3222 		return dpp_reconfigure(dut, conn, cmd);
3223 
3224 	if (!bs) {
3225 		send_resp(dut, conn, SIGMA_ERROR,
3226 			  "errorCode,Missing DPPBS");
3227 		return STATUS_SENT_ERROR;
3228 	}
3229 
3230 	if (strcasecmp(type, "GetLocalBootstrap") == 0)
3231 		return dpp_get_local_bootstrap(dut, conn, cmd, 1, NULL);
3232 	if (strcasecmp(type, "SetPeerBootstrap") == 0)
3233 		return dpp_set_peer_bootstrap(dut, conn, cmd);
3234 	if (strcasecmp(type, "ManualDPP") == 0)
3235 		return dpp_manual_dpp(dut, conn, cmd);
3236 	if (strcasecmp(type, "AutomaticDPP") == 0)
3237 		return dpp_automatic_dpp(dut, conn, cmd);
3238 
3239 	send_resp(dut, conn, SIGMA_ERROR,
3240 		  "errorCode,Unsupported DPPActionType");
3241 	return STATUS_SENT_ERROR;
3242 }
3243