xref: /wlan-dirver/utils/sigma-dut/dpp.c (revision efe4ae751cf8296135d56c6a2429f4611118a5e5)
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 
16 #ifdef ANDROID
17 char *dpp_qrcode_file = "/sdcard/wpadebug_qrdata.txt";
18 #endif /* ANDROID */
19 
20 
21 static int sigma_dut_is_ap(struct sigma_dut *dut)
22 {
23 	return dut->device_type == AP_unknown ||
24 		dut->device_type == AP_testbed ||
25 		dut->device_type == AP_dut;
26 }
27 
28 
29 static int dpp_hostapd_run(struct sigma_dut *dut)
30 {
31 	if (dut->hostapd_running)
32 		return 0;
33 
34 	sigma_dut_print(dut, DUT_MSG_INFO,
35 			"Starting hostapd in unconfigured state for DPP");
36 	snprintf(dut->ap_ssid, sizeof(dut->ap_ssid), "unconfigured");
37 	if (!dut->ap_oper_chn)
38 		dut->ap_channel = 11;
39 	dut->ap_is_dual = 0;
40 	dut->ap_mode = dut->ap_channel <= 14 ? AP_11ng : AP_11na;
41 	dut->ap_key_mgmt = AP_OPEN;
42 	dut->ap_cipher = AP_PLAIN;
43 	if (!dut->ap_dpp_conf_addr || !dut->ap_dpp_conf_pkhash)
44 		dut->ap_start_disabled = 1;
45 	return cmd_ap_config_commit(dut, NULL, NULL) == 1 ? 0 : -1;
46 }
47 
48 
49 static int dpp_hostapd_beacon(struct sigma_dut *dut)
50 {
51 	const char *ifname = dut->hostapd_ifname;
52 
53 	if (!dut->ap_start_disabled)
54 		return 0;
55 
56 	if (!ifname ||
57 	    wpa_command(ifname, "SET start_disabled 0") < 0 ||
58 	    wpa_command(ifname, "DISABLE") < 0 ||
59 	    wpa_command(ifname, "ENABLE") < 0)
60 		return -1;
61 
62 	dut->ap_start_disabled = 0;
63 	return 0;
64 }
65 
66 
67 static const char * dpp_get_curve(struct sigma_cmd *cmd, const char *arg)
68 {
69 	const char *val = get_param(cmd, arg);
70 
71 	if (!val)
72 		val = "P-256";
73 	else if (strcasecmp(val, "BP-256R1") == 0)
74 		val = "BP-256";
75 	else if (strcasecmp(val, "BP-384R1") == 0)
76 		val = "BP-384";
77 	else if (strcasecmp(val, "BP-512R1") == 0)
78 		val = "BP-512";
79 
80 	return val;
81 }
82 
83 
84 static enum sigma_cmd_result
85 dpp_get_local_bootstrap(struct sigma_dut *dut, struct sigma_conn *conn,
86 			struct sigma_cmd *cmd, int send_result, int *success)
87 {
88 	const char *curve = dpp_get_curve(cmd, "DPPCryptoIdentifier");
89 	const char *bs = get_param(cmd, "DPPBS");
90 	const char *chan_list = get_param(cmd, "DPPChannelList");
91 	char *pos, mac[50], buf[200], resp[1000], hex[2000];
92 	const char *ifname = get_station_ifname(dut);
93 	int res;
94 	const char *type;
95 
96 	if (success)
97 		*success = 0;
98 	if (strcasecmp(bs, "QR") == 0) {
99 		type = "qrcode";
100 	} else if (strcasecmp(bs, "NFC") == 0) {
101 		type ="nfc-uri";
102 	} else {
103 		send_resp(dut, conn, SIGMA_ERROR,
104 			  "errorCode,Unsupported DPPBS");
105 		return STATUS_SENT_ERROR;
106 	}
107 
108 	if (sigma_dut_is_ap(dut)) {
109 		u8 bssid[ETH_ALEN];
110 
111 		if (!dut->hostapd_ifname) {
112 			sigma_dut_print(dut, DUT_MSG_ERROR,
113 					"hostapd ifname not specified (-j)");
114 			return ERROR_SEND_STATUS;
115 		}
116 		ifname = dut->hostapd_ifname;
117 		if (get_hwaddr(dut->hostapd_ifname, bssid) < 0) {
118 			sigma_dut_print(dut, DUT_MSG_ERROR,
119 					"Could not get MAC address for %s",
120 					dut->hostapd_ifname);
121 			return ERROR_SEND_STATUS;
122 		}
123 		snprintf(mac, sizeof(mac), "%02x%02x%02x%02x%02x%02x",
124 			 bssid[0], bssid[1], bssid[2],
125 			 bssid[3], bssid[4], bssid[5]);
126 	} else {
127 		if (get_wpa_status(ifname, "address", mac, sizeof(mac)) < 0) {
128 			send_resp(dut, conn, SIGMA_ERROR,
129 				  "errorCode,Failed to get own MAC address from wpa_supplicant");
130 			return STATUS_SENT_ERROR;
131 		}
132 	}
133 
134 	pos = mac;
135 	while (*pos) {
136 		if (*pos == ':')
137 			memmove(pos, pos + 1, strlen(pos));
138 		else
139 			pos++;
140 	}
141 
142 	if (sigma_dut_is_ap(dut) && dpp_hostapd_run(dut) < 0) {
143 		send_resp(dut, conn, SIGMA_ERROR,
144 			  "errorCode,Failed to start hostapd");
145 		return STATUS_SENT_ERROR;
146 	}
147 
148 	if (chan_list &&
149 	    (strcmp(chan_list, "0/0") == 0 || chan_list[0] == '\0')) {
150 		/* No channel list */
151 		res = snprintf(buf, sizeof(buf),
152 			       "DPP_BOOTSTRAP_GEN type=%s curve=%s mac=%s",
153 			       type, curve, mac);
154 	} else if (chan_list) {
155 		/* Channel list override (CTT case) - space separated tuple(s)
156 		 * of OperatingClass/Channel; convert to wpa_supplicant/hostapd
157 		 * format: comma separated tuples */
158 		strlcpy(resp, chan_list, sizeof(resp));
159 		for (pos = resp; *pos; pos++) {
160 			if (*pos == ' ')
161 				*pos = ',';
162 		}
163 		res = snprintf(buf, sizeof(buf),
164 			       "DPP_BOOTSTRAP_GEN type=%s curve=%s chan=%s mac=%s",
165 			       type, curve, resp, mac);
166 	} else {
167 		int channel = 11;
168 
169 		/* Default channel list (normal DUT case) */
170 		if (sigma_dut_is_ap(dut) && dut->hostapd_running &&
171 		    dut->ap_oper_chn &&
172 		    dut->ap_channel > 0 && dut->ap_channel <= 13)
173 			channel = dut->ap_channel;
174 		res = snprintf(buf, sizeof(buf),
175 			       "DPP_BOOTSTRAP_GEN type=%s curve=%s chan=81/%d mac=%s",
176 			       type, curve, channel, mac);
177 	}
178 
179 	if (res < 0 || res >= sizeof(buf) ||
180 	    wpa_command_resp(ifname, buf, resp, sizeof(resp)) < 0 ||
181 	    strncmp(resp, "FAIL", 4) == 0)
182 		return ERROR_SEND_STATUS;
183 	dut->dpp_local_bootstrap = atoi(resp);
184 	snprintf(buf, sizeof(buf), "DPP_BOOTSTRAP_GET_URI %d",
185 		 atoi(resp));
186 	if (wpa_command_resp(ifname, buf, resp, sizeof(resp)) < 0 ||
187 	    strncmp(resp, "FAIL", 4) == 0)
188 		return ERROR_SEND_STATUS;
189 
190 	sigma_dut_print(dut, DUT_MSG_DEBUG, "URI: %s", resp);
191 
192 	if (send_result) {
193 		ascii2hexstr(resp, hex);
194 		res = snprintf(resp, sizeof(resp), "BootstrappingData,%s", hex);
195 		send_resp(dut, conn, SIGMA_COMPLETE,
196 			  res >= 0 && res < sizeof(resp) ? resp : NULL);
197 	}
198 
199 	if (success)
200 		*success = 1;
201 	return STATUS_SENT;
202 }
203 
204 
205 static enum sigma_cmd_result dpp_set_peer_bootstrap(struct sigma_dut *dut,
206 						    struct sigma_conn *conn,
207 						    struct sigma_cmd *cmd)
208 {
209 	const char *val = get_param(cmd, "DPPBootstrappingdata");
210 	char uri[1000];
211 	int res;
212 
213 	if (!val) {
214 		send_resp(dut, conn, SIGMA_ERROR,
215 			  "errorCode,Missing DPPBootstrappingdata");
216 		return STATUS_SENT_ERROR;
217 	}
218 
219 	res = parse_hexstr(val, (unsigned char *) uri, sizeof(uri));
220 	if (res < 0 || (size_t) res >= sizeof(uri))
221 		return ERROR_SEND_STATUS;
222 	uri[res] = '\0';
223 	sigma_dut_print(dut, DUT_MSG_DEBUG, "URI: %s", uri);
224 	free(dut->dpp_peer_uri);
225 	dut->dpp_peer_uri = strdup(uri);
226 
227 	return SUCCESS_SEND_STATUS;
228 }
229 
230 
231 static int dpp_hostapd_conf_update(struct sigma_dut *dut,
232 				   struct sigma_conn *conn, const char *ifname,
233 				   struct wpa_ctrl *ctrl)
234 {
235 	int res;
236 	char buf[2000], buf2[2500], *pos, *pos2;
237 	const char *conf_data_events[] = {
238 		"DPP-CONNECTOR",
239 		"DPP-CONFOBJ-PASS",
240 		"DPP-CONFOBJ-PSK",
241 		"DPP-C-SIGN-KEY",
242 		"DPP-NET-ACCESS-KEY",
243 		NULL
244 	};
245 	unsigned int old_timeout;
246 	int legacy_akm, dpp_akm;
247 	char *connector = NULL, *psk = NULL, *csign = NULL,
248 		*net_access_key = NULL;
249 	char pass[64];
250 	int pass_len = 0;
251 	int ret = 0;
252 
253 	sigma_dut_print(dut, DUT_MSG_INFO,
254 			"Update hostapd configuration based on DPP Config Object");
255 
256 	if (wpa_command(ifname, "SET wpa 2") < 0 ||
257 	    wpa_command(ifname, "SET wpa_key_mgmt DPP") < 0 ||
258 	    wpa_command(ifname, "SET ieee80211w 1") < 0 ||
259 	    wpa_command(ifname, "SET rsn_pairwise CCMP") < 0) {
260 		send_resp(dut, conn, SIGMA_ERROR,
261 			  "errorCode,Failed to update AP security parameters");
262 		goto out;
263 	}
264 
265 	res = get_wpa_cli_event(dut, ctrl, "DPP-CONFOBJ-AKM", buf, sizeof(buf));
266 	if (res < 0) {
267 		send_resp(dut, conn, SIGMA_ERROR,
268 			  "errorCode,No DPP-CONFOBJ-AKM");
269 		goto out;
270 	}
271 	pos = strchr(buf, ' ');
272 	if (!pos)
273 		return -2;
274 	pos++;
275 	sigma_dut_print(dut, DUT_MSG_INFO,
276 			"DPP: Config Object AKM: %s", pos);
277 	legacy_akm = strstr(pos, "psk") != NULL || strstr(pos, "sae") != NULL;
278 	dpp_akm = strstr(pos, "dpp") != NULL;
279 
280 	res = get_wpa_cli_event(dut, ctrl, "DPP-CONFOBJ-SSID",
281 				buf, sizeof(buf));
282 	if (res < 0) {
283 		send_resp(dut, conn, SIGMA_ERROR,
284 			  "errorCode,No DPP-CONFOBJ-SSID");
285 		goto out;
286 	}
287 	pos = strchr(buf, ' ');
288 	if (!pos)
289 		return -2;
290 	pos++;
291 	sigma_dut_print(dut, DUT_MSG_INFO,
292 			"DPP: Config Object SSID: %s", pos);
293 	snprintf(buf2, sizeof(buf2), "SET ssid %s", pos);
294 	if (wpa_command(ifname, buf2) < 0) {
295 		send_resp(dut, conn, SIGMA_ERROR,
296 			  "errorCode,Failed to update AP SSID");
297 		goto out;
298 	}
299 
300 	if (wpa_command(ifname, "SET utf8_ssid 1") < 0) {
301 		send_resp(dut, conn, SIGMA_ERROR,
302 			  "errorCode,Failed to update AP UTF-8 SSID capa");
303 		goto out;
304 	}
305 
306 	while ((dpp_akm && (!connector || !csign || !net_access_key)) ||
307 	       (legacy_akm && !pass_len && !psk)) {
308 		res = get_wpa_cli_events(dut, ctrl, conf_data_events,
309 					 buf, sizeof(buf));
310 		if (res < 0) {
311 			send_resp(dut, conn, SIGMA_ERROR,
312 				  "errorCode,Not all config object information received");
313 			goto out;
314 		}
315 
316 		if (strstr(buf, "DPP-CONNECTOR")) {
317 			pos = strchr(buf, ' ');
318 			if (!pos) {
319 				ret = -2;
320 				goto out;
321 			}
322 			pos++;
323 			sigma_dut_print(dut, DUT_MSG_INFO, "DPP: Connector: %s",
324 					pos);
325 			if (!connector)
326 				connector = strdup(pos);
327 		} else if (strstr(buf, "DPP-C-SIGN-KEY")) {
328 			pos = strchr(buf, ' ');
329 			if (!pos) {
330 				ret = -2;
331 				goto out;
332 			}
333 			pos++;
334 			sigma_dut_print(dut, DUT_MSG_INFO,
335 					"DPP: C-sign-key: %s", pos);
336 			if (!csign)
337 				csign = strdup(pos);
338 		} else if (strstr(buf, "DPP-NET-ACCESS-KEY")) {
339 			pos = strchr(buf, ' ');
340 			if (!pos) {
341 				ret = -2;
342 				goto out;
343 			}
344 			pos++;
345 			if (!net_access_key)
346 				net_access_key = strdup(pos);
347 		} else if (strstr(buf, "DPP-CONFOBJ-PASS")) {
348 			pos = strchr(buf, ' ');
349 			if (!pos) {
350 				ret = -2;
351 				goto out;
352 			}
353 			pos++;
354 			pass_len = parse_hexstr(pos, (u8 *) pass, sizeof(pass));
355 			if (pass_len < 0 || (size_t) pass_len >= sizeof(pass)) {
356 				ret = -2;
357 				goto out;
358 			}
359 			pass[pass_len] = '\0';
360 			sigma_dut_print(dut, DUT_MSG_INFO,
361 					"DPP: Passphrase: %s", pass);
362 		} else if (strstr(buf, "DPP-CONFOBJ-PSK")) {
363 			pos = strchr(buf, ' ');
364 			if (!pos) {
365 				ret = -2;
366 				goto out;
367 			}
368 			pos++;
369 			sigma_dut_print(dut, DUT_MSG_INFO, "DPP: PSK: %s", pos);
370 			if (!psk)
371 				psk = strdup(pos);
372 		}
373 	}
374 
375 	if ((!connector || !dpp_akm) &&
376 	    wpa_command(ifname, "SET wpa_key_mgmt WPA-PSK") < 0) {
377 		send_resp(dut, conn, SIGMA_ERROR,
378 			  "errorCode,Failed to update AP security parameters");
379 		goto out;
380 	}
381 
382 	if (connector && dpp_akm && legacy_akm &&
383 	    wpa_command(ifname, "SET wpa_key_mgmt DPP WPA-PSK") < 0) {
384 		send_resp(dut, conn, SIGMA_ERROR,
385 			  "errorCode,Failed to update AP security parameters");
386 		goto out;
387 	}
388 
389 	if (pass_len) {
390 		snprintf(buf2, sizeof(buf2), "SET wpa_passphrase %s",
391 			 pass);
392 		if (wpa_command(ifname, buf2) < 0) {
393 			send_resp(dut, conn, SIGMA_ERROR,
394 				  "errorCode,Failed to set passphrase");
395 			goto out;
396 		}
397 	} else if (psk) {
398 		snprintf(buf2, sizeof(buf2), "SET wpa_psk %s", psk);
399 		if (wpa_command(ifname, buf2) < 0) {
400 			send_resp(dut, conn, SIGMA_ERROR,
401 				  "errorCode,Failed to set PSK");
402 			goto out;
403 		}
404 	}
405 
406 	if (connector) {
407 		snprintf(buf2, sizeof(buf2), "SET dpp_connector %s", connector);
408 		if (wpa_command(ifname, buf2) < 0) {
409 			send_resp(dut, conn, SIGMA_ERROR,
410 				  "errorCode,Failed to update AP Connector");
411 			goto out;
412 		}
413 	}
414 
415 	if (csign) {
416 		snprintf(buf2, sizeof(buf2), "SET dpp_csign %s", csign);
417 		if (wpa_command(ifname, buf2) < 0) {
418 			send_resp(dut, conn, SIGMA_ERROR,
419 				  "errorCode,Failed to update AP C-sign-key");
420 			goto out;
421 		}
422 	}
423 
424 	if (net_access_key) {
425 		pos2 = strchr(net_access_key, ' ');
426 		if (pos2)
427 			*pos2++ = '\0';
428 		sigma_dut_print(dut, DUT_MSG_INFO, "DPP: netAccessKey: %s",
429 				net_access_key);
430 		snprintf(buf2, sizeof(buf2), "SET dpp_netaccesskey %s",
431 			 net_access_key);
432 		if (wpa_command(ifname, buf2) < 0) {
433 			send_resp(dut, conn, SIGMA_ERROR,
434 				  "errorCode,Failed to update AP netAccessKey");
435 			goto out;
436 		}
437 		if (pos2) {
438 			sigma_dut_print(dut, DUT_MSG_INFO,
439 					"DPP: netAccessKey expiry: %s", pos2);
440 			snprintf(buf2, sizeof(buf2),
441 				 "SET dpp_netaccesskey_expiry %s", pos2);
442 			if (wpa_command(ifname, buf2) < 0) {
443 				send_resp(dut, conn, SIGMA_ERROR,
444 					  "errorCode,Failed to update AP netAccessKey expiry");
445 				goto out;
446 			}
447 		}
448 	}
449 
450 	if (wpa_command(ifname, "SET start_disabled 0") < 0 &&
451 	    dut->ap_start_disabled) {
452 		send_resp(dut, conn, SIGMA_ERROR,
453 			  "errorCode,Failed to update AP security parameters");
454 		goto out;
455 	}
456 	dut->ap_start_disabled = 0;
457 
458 	/* Wait for a possible Configuration Result to be sent */
459 	old_timeout = dut->default_timeout;
460 	dut->default_timeout = 1;
461 	get_wpa_cli_event(dut, ctrl, "DPP-TX-STATUS", buf, sizeof(buf));
462 	dut->default_timeout = old_timeout;
463 	if (wpa_command(ifname, "DISABLE") < 0 ||
464 	    wpa_command(ifname, "ENABLE") < 0) {
465 		send_resp(dut, conn, SIGMA_ERROR,
466 			  "errorCode,Failed to update AP configuration");
467 		goto out;
468 	}
469 
470 	res = get_wpa_cli_event(dut, ctrl, "AP-ENABLED", buf, sizeof(buf));
471 	if (res < 0) {
472 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,No AP-ENABLED");
473 		goto out;
474 	}
475 
476 	ret = 1;
477 out:
478 	free(connector);
479 	free(psk);
480 	free(csign);
481 	free(net_access_key);
482 	return ret;
483 }
484 
485 
486 struct dpp_test_info {
487 	const char *step;
488 	const char *frame;
489 	const char *attr;
490 	int value;
491 };
492 
493 static const struct dpp_test_info dpp_tests[] = {
494 	{ "InvalidValue", "AuthenticationRequest", "WrappedData", 1 },
495 	{ "InvalidValue", "AuthenticationResponse", "WrappedData", 2 },
496 	{ "InvalidValue", "AuthenticationResponse", "PrimaryWrappedData", 2 },
497 	{ "InvalidValue", "AuthenticationConfirm", "WrappedData", 3 },
498 	{ "InvalidValue", "PKEXCRRequest", "WrappedData", 4 },
499 	{ "InvalidValue", "PKEXCRResponse", "WrappedData", 5 },
500 	{ "InvalidValue", "ConfigurationRequest", "WrappedData", 6 },
501 	{ "InvalidValue", "ConfigurationResponse", "WrappedData", 7 },
502 	{ "InvalidValue", "AuthenticationRequest", "InitCapabilities", 8 },
503 	{ "MissingAttribute", "AuthenticationRequest", "RespBSKeyHash", 10 },
504 	{ "MissingAttribute", "AuthenticationRequest", "InitBSKeyHash", 11 },
505 	{ "MissingAttribute", "AuthenticationRequest", "InitProtocolKey", 12 },
506 	{ "MissingAttribute", "AuthenticationRequest", "InitNonce", 13 },
507 	{ "MissingAttribute", "AuthenticationRequest", "InitCapabilities", 14 },
508 	{ "MissingAttribute", "AuthenticationRequest", "WrappedData", 15 },
509 	{ "MissingAttribute", "AuthenticationResponse", "DPPStatus", 16 },
510 	{ "MissingAttribute", "AuthenticationResponse", "RespBSKeyHash", 17 },
511 	{ "MissingAttribute", "AuthenticationResponse", "InitBSKeyHash", 18 },
512 	{ "MissingAttribute", "AuthenticationResponse", "RespProtocolKey", 19 },
513 	{ "MissingAttribute", "AuthenticationResponse", "RespNonce", 20 },
514 	{ "MissingAttribute", "AuthenticationResponse", "InitNonce", 21 },
515 	{ "MissingAttribute", "AuthenticationResponse", "RespCapabilities",
516 	  22 },
517 	{ "MissingAttribute", "AuthenticationResponse", "RespAuthTag", 23 },
518 	{ "MissingAttribute", "AuthenticationResponse", "WrappedData", 24 },
519 	{ "MissingAttribute", "AuthenticationResponse", "PrimaryWrappedData",
520 	  24 },
521 	{ "MissingAttribute", "AuthenticationConfirm", "DPPStatus", 25 },
522 	{ "MissingAttribute", "AuthenticationConfirm", "RespBSKeyHash", 26 },
523 	{ "MissingAttribute", "AuthenticationConfirm", "InitBSKeyHash", 27 },
524 	{ "MissingAttribute", "AuthenticationConfirm", "InitAuthTag", 28 },
525 	{ "MissingAttribute", "AuthenticationConfirm", "WrappedData", 29 },
526 	{ "InvalidValue", "AuthenticationResponse", "InitNonce", 30 },
527 	{ "InvalidValue", "AuthenticationResponse", "RespCapabilities", 31 },
528 	{ "InvalidValue", "AuthenticationResponse", "RespAuthTag", 32 },
529 	{ "InvalidValue", "AuthenticationConfirm", "InitAuthTag", 33 },
530 	{ "MissingAttribute", "PKEXExchangeRequest", "FiniteCyclicGroup", 34 },
531 	{ "MissingAttribute", "PKEXExchangeRequest", "EncryptedKey", 35 },
532 	{ "MissingAttribute", "PKEXExchangeResponse", "DPPStatus", 36 },
533 	{ "MissingAttribute", "PKEXExchangeResponse", "EncryptedKey", 37 },
534 	{ "MissingAttribute", "PKEXCRRequest", "BSKey", 38 },
535 	{ "MissingAttribute", "PKEXCRRequest", "InitAuthTag", 39 },
536 	{ "MissingAttribute", "PKEXCRRequest", "WrappedData", 40 },
537 	{ "MissingAttribute", "PKEXCRResponse", "BSKey", 41 },
538 	{ "MissingAttribute", "PKEXCRResponse", "RespAuthTag", 42 },
539 	{ "MissingAttribute", "PKEXCRResponse", "WrappedData", 43 },
540 	{ "InvalidValue", "PKEXExchangeRequest", "EncryptedKey", 44 },
541 	{ "InvalidValue", "PKEXExchangeResponse", "EncryptedKey", 45 },
542 	{ "InvalidValue", "PKEXExchangeResponse", "DPPStatus", 46 },
543 	{ "InvalidValue", "PKEXCRRequest", "BSKey", 47 },
544 	{ "InvalidValue", "PKEXCRResponse", "BSKey", 48 },
545 	{ "InvalidValue", "PKEXCRRequest", "InitAuthTag", 49 },
546 	{ "InvalidValue", "PKEXCRResponse", "RespAuthTag", 50 },
547 	{ "MissingAttribute", "ConfigurationRequest", "EnrolleeNonce", 51 },
548 	{ "MissingAttribute", "ConfigurationRequest", "ConfigAttr", 52 },
549 	{ "MissingAttribute", "ConfigurationRequest", "WrappedData", 53 },
550 	{ "MissingAttribute", "ConfigurationResponse", "EnrolleeNonce", 54 },
551 	{ "MissingAttribute", "ConfigurationResponse", "ConfigObj", 55 },
552 	{ "MissingAttribute", "ConfigurationResponse", "DPPStatus", 56 },
553 	{ "MissingAttribute", "ConfigurationResponse", "WrappedData", 57 },
554 	{ "InvalidValue", "ConfigurationResponse", "DPPStatus", 58 },
555 	{ "InvalidValue", "ConfigurationResponse", "EnrolleeNonce", 59 },
556 	{ "MissingAttribute", "PeerDiscoveryRequest", "TransactionID", 60 },
557 	{ "MissingAttribute", "PeerDiscoveryRequest", "Connector", 61 },
558 	{ "MissingAttribute", "PeerDiscoveryResponse", "TransactionID", 62 },
559 	{ "MissingAttribute", "PeerDiscoveryResponse", "DPPStatus", 63 },
560 	{ "MissingAttribute", "PeerDiscoveryResponse", "Connector", 64 },
561 	{ "InvalidValue", "AuthenticationRequest", "InitProtocolKey", 66 },
562 	{ "InvalidValue", "AuthenticationResponse", "RespProtocolKey", 67 },
563 	{ "InvalidValue", "AuthenticationRequest", "RespBSKeyHash", 68 },
564 	{ "InvalidValue", "AuthenticationRequest", "InitBSKeyHash", 69 },
565 	{ "InvalidValue", "AuthenticationResponse", "RespBSKeyHash", 70 },
566 	{ "InvalidValue", "AuthenticationResponse", "InitBSKeyHash", 71 },
567 	{ "InvalidValue", "AuthenticationConfirm", "RespBSKeyHash", 72 },
568 	{ "InvalidValue", "AuthenticationConfirm", "InitBSKeyHash", 73 },
569 	{ "InvalidValue", "AuthenticationResponse", "DPPStatus", 74 },
570 	{ "InvalidValue", "AuthenticationConfirm", "DPPStatus", 75 },
571 	{ "InvalidValue", "ConfigurationRequest", "ConfigAttr", 76 },
572 	{ "InvalidValue", "PeerDiscoveryResponse", "TransactionID", 77 },
573 	{ "InvalidValue", "PeerDiscoveryResponse", "DPPStatus", 78 },
574 	{ "InvalidValue", "PeerDiscoveryResponse", "Connector", 79 },
575 	{ "InvalidValue", "PeerDiscoveryRequest", "Connector", 80 },
576 	{ "InvalidValue", "AuthenticationRequest", "InitNonce", 81 },
577 	{ "InvalidValue", "PeerDiscoveryRequest", "TransactionID", 82 },
578 	{ "InvalidValue", "ConfigurationRequest", "EnrolleeNonce", 83 },
579 	{ "Timeout", "PKEXExchangeResponse", NULL, 84 },
580 	{ "Timeout", "PKEXCRRequest", NULL, 85 },
581 	{ "Timeout", "PKEXCRResponse", NULL, 86 },
582 	{ "Timeout", "AuthenticationRequest", NULL, 87 },
583 	{ "Timeout", "AuthenticationResponse", NULL, 88 },
584 	{ "Timeout", "AuthenticationConfirm", NULL, 89 },
585 	{ "Timeout", "ConfigurationRequest", NULL, 90 },
586 	{ NULL, NULL, NULL, 0 }
587 };
588 
589 
590 static int dpp_get_test(const char *step, const char *frame, const char *attr)
591 {
592 	int i;
593 
594 	for (i = 0; dpp_tests[i].step; i++) {
595 		if (strcasecmp(step, dpp_tests[i].step) == 0 &&
596 		    strcasecmp(frame, dpp_tests[i].frame) == 0 &&
597 		    ((!attr && dpp_tests[i].attr == NULL) ||
598 		     (attr && strcasecmp(attr, dpp_tests[i].attr) == 0)))
599 			return dpp_tests[i].value;
600 	}
601 
602 	return -1;
603 }
604 
605 
606 static int dpp_wait_tx(struct sigma_dut *dut, struct wpa_ctrl *ctrl,
607 		       int frame_type)
608 {
609 	char buf[200], tmp[20];
610 	int res;
611 
612 	snprintf(tmp, sizeof(tmp), "type=%d", frame_type);
613 	for (;;) {
614 		res = get_wpa_cli_event(dut, ctrl, "DPP-TX", buf, sizeof(buf));
615 		if (res < 0)
616 			return -1;
617 		if (strstr(buf, tmp) != NULL)
618 			break;
619 	}
620 
621 	return 0;
622 }
623 
624 
625 static int dpp_wait_tx_status(struct sigma_dut *dut, struct wpa_ctrl *ctrl,
626 			      int frame_type)
627 {
628 	char buf[200], tmp[20];
629 	int res;
630 
631 	snprintf(tmp, sizeof(tmp), "type=%d", frame_type);
632 	for (;;) {
633 		res = get_wpa_cli_event(dut, ctrl, "DPP-TX", buf, sizeof(buf));
634 		if (res < 0)
635 			return -1;
636 		if (strstr(buf, tmp) != NULL)
637 			break;
638 	}
639 
640 	res = get_wpa_cli_event(dut, ctrl, "DPP-TX-STATUS",
641 				buf, sizeof(buf));
642 	if (res < 0 || strstr(buf, "result=FAILED") != NULL)
643 		return -1;
644 
645 	return 0;
646 }
647 
648 
649 static int dpp_wait_rx(struct sigma_dut *dut, struct wpa_ctrl *ctrl,
650 		       int frame_type, unsigned int max_wait)
651 {
652 	char buf[200], tmp[20];
653 	int res;
654 	unsigned int old_timeout;
655 
656 	old_timeout = dut->default_timeout;
657 	if (max_wait > 0 && dut->default_timeout > max_wait)
658 		dut->default_timeout = max_wait;
659 
660 	snprintf(tmp, sizeof(tmp), "type=%d", frame_type);
661 	for (;;) {
662 		res = get_wpa_cli_event(dut, ctrl, "DPP-RX", buf, sizeof(buf));
663 		if (res < 0) {
664 			dut->default_timeout = old_timeout;
665 			return -1;
666 		}
667 		if (strstr(buf, tmp) != NULL)
668 			break;
669 	}
670 
671 	dut->default_timeout = old_timeout;
672 	return 0;
673 }
674 
675 
676 static int dpp_wait_rx_conf_req(struct sigma_dut *dut, struct wpa_ctrl *ctrl,
677 				unsigned int max_wait)
678 {
679 	char buf[200];
680 	int res;
681 	unsigned int old_timeout;
682 
683 	old_timeout = dut->default_timeout;
684 	if (max_wait > 0 && dut->default_timeout > max_wait)
685 		dut->default_timeout = max_wait;
686 
687 	for (;;) {
688 		res = get_wpa_cli_event(dut, ctrl, "DPP-CONF-REQ-RX",
689 					buf, sizeof(buf));
690 		if (res < 0) {
691 			dut->default_timeout = old_timeout;
692 			return -1;
693 		}
694 
695 		break;
696 	}
697 
698 	dut->default_timeout = old_timeout;
699 	return 0;
700 }
701 
702 
703 static int dpp_scan_peer_qrcode(struct sigma_dut *dut)
704 {
705 #ifdef ANDROID
706 	char buf[100];
707 	char *buf2 = NULL;
708 	FILE *fp = NULL;
709 	uint32_t length;
710 	unsigned int count;
711 
712 	unlink(dpp_qrcode_file);
713 
714 	snprintf(buf, sizeof(buf),
715 		 "am start -n w1.fi.wpadebug/w1.fi.wpadebug.QrCodeReadActivity");
716 	if (system(buf) != 0) {
717 		sigma_dut_print(dut, DUT_MSG_ERROR,
718 				"Failed to launch QR Code scanner");
719 		return -1;
720 	}
721 
722 	count = 0;
723 	while (!(fp = fopen(dpp_qrcode_file, "r"))) {
724 		if (count > dut->default_timeout) {
725 			sigma_dut_print(dut, DUT_MSG_ERROR,
726 					"Failed to open dpp_qrcode_file - QR Code scanning timed out");
727 			return -1;
728 		}
729 
730 		sleep(1);
731 		count++;
732 	}
733 
734 	if (fseek(fp, 0, SEEK_END) < 0 || (length = ftell(fp)) <= 0 ||
735 	    fseek(fp, 0, SEEK_SET) < 0) {
736 		sigma_dut_print(dut, DUT_MSG_ERROR,
737 				"Failed to get QR Code result file length");
738 		fclose(fp);
739 		return -1;
740 	}
741 
742 	buf2 = malloc(length + 1);
743 	if (!buf2) {
744 		fclose(fp);
745 		return -1;
746 	}
747 
748 	if (fread(buf2, 1, length, fp) != length) {
749 		fclose(fp);
750 		free(buf2);
751 		return -1;
752 	}
753 
754 	fclose(fp);
755 	buf2[length] = '\0';
756 
757 	free(dut->dpp_peer_uri);
758 	dut->dpp_peer_uri = strdup(buf2);
759 	free(buf2);
760 	return 0;
761 #else /* ANDROID */
762 	pid_t pid;
763 	int pid_status;
764 	int pipe_out[2];
765 	char buf[4000], *pos;
766 	ssize_t len;
767 	int res = -1, ret;
768 	struct timeval tv;
769 	fd_set rfd;
770 
771 	if (pipe(pipe_out) != 0) {
772 		perror("pipe");
773 		return -1;
774 	}
775 
776 	pid = fork();
777 	if (pid < 0) {
778 		perror("fork");
779 		close(pipe_out[0]);
780 		close(pipe_out[1]);
781 		return -1;
782 	}
783 
784 	if (pid == 0) {
785 		char *argv[4] = { "zbarcam", "--raw", "--prescale=320x240",
786 				  NULL };
787 
788 		dup2(pipe_out[1], STDOUT_FILENO);
789 		close(pipe_out[0]);
790 		close(pipe_out[1]);
791 		execv("/usr/bin/zbarcam", argv);
792 		perror("execv");
793 		exit(0);
794 		return -1;
795 	}
796 
797 	close(pipe_out[1]);
798 
799 	FD_ZERO(&rfd);
800 	FD_SET(pipe_out[0], &rfd);
801 	tv.tv_sec = dut->default_timeout;
802 	tv.tv_usec = 0;
803 
804 	ret = select(pipe_out[0] + 1, &rfd, NULL, NULL, &tv);
805 	if (ret < 0) {
806 		perror("select");
807 		goto out;
808 	}
809 	if (ret == 0) {
810 		sigma_dut_print(dut, DUT_MSG_DEBUG,
811 				"QR Code scanning timed out");
812 		goto out;
813 	}
814 
815 	len = read(pipe_out[0], buf, sizeof(buf));
816 	if (len <= 0)
817 		goto out;
818 	if (len == sizeof(buf))
819 		len--;
820 	buf[len] = '\0';
821 	pos = strchr(buf, '\n');
822 	if (pos)
823 		*pos = '\0';
824 	sigma_dut_print(dut, DUT_MSG_DEBUG, "URI from QR scanner: %s", buf);
825 
826 	free(dut->dpp_peer_uri);
827 	dut->dpp_peer_uri = strdup(buf);
828 	res = 0;
829 out:
830 	close(pipe_out[0]);
831 	kill(pid, SIGTERM);
832 	waitpid(pid, &pid_status, 0);
833 
834 	return res;
835 #endif /* ANDROID */
836 }
837 
838 
839 static int dpp_display_own_qrcode(struct sigma_dut *dut)
840 {
841 	char buf[200], resp[2000];
842 	const char *ifname = get_station_ifname(dut);
843 #ifdef ANDROID
844 	FILE *fp;
845 #else /* ANDROID */
846 	pid_t pid;
847 	int pid_status;
848 #endif /* ANDROID */
849 
850 	snprintf(buf, sizeof(buf), "DPP_BOOTSTRAP_GET_URI %d",
851 		 dut->dpp_local_bootstrap);
852 	if (wpa_command_resp(ifname, buf, resp, sizeof(resp)) < 0 ||
853 	    strncmp(resp, "FAIL", 4) == 0)
854 		return -2;
855 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Own bootstrap URI: %s", resp);
856 
857 #ifdef ANDROID
858 	unlink(dpp_qrcode_file);
859 
860 	fp = fopen(dpp_qrcode_file, "w");
861 	if (!fp) {
862 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open file %s",
863 				dpp_qrcode_file);
864 		return -2;
865 	}
866 
867 	fwrite(resp, 1, strlen(resp), fp);
868 	fclose(fp);
869 
870 	snprintf(buf, sizeof(buf),
871 		 "am start -n w1.fi.wpadebug/w1.fi.wpadebug.QrCodeDisplayActivity");
872 	if (system(buf) != 0) {
873 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to display QR Code");
874 		return -1;
875 	}
876 #else /* ANDROID */
877 	pid = fork();
878 	if (pid < 0) {
879 		perror("fork");
880 		return -1;
881 	}
882 
883 	if (pid == 0) {
884 		char *argv[3] = { "qr", resp, NULL };
885 
886 		execv("/usr/bin/qr", argv);
887 		perror("execv");
888 		exit(0);
889 		return -1;
890 	}
891 
892 	waitpid(pid, &pid_status, 0);
893 #endif /* ANDROID */
894 
895 	return 0;
896 }
897 
898 
899 static int dpp_process_auth_response(struct sigma_dut *dut,
900 				     struct sigma_conn *conn,
901 				     struct wpa_ctrl *ctrl,
902 				     const char **auth_events,
903 				     const char *action_type,
904 				     int check_mutual, char *buf, size_t buflen)
905 {
906 	int res;
907 
908 	res = get_wpa_cli_events(dut, ctrl, auth_events, buf, buflen);
909 	if (res < 0) {
910 		send_resp(dut, conn, SIGMA_COMPLETE,
911 			  "BootstrapResult,OK,AuthResult,Timeout");
912 		return res;
913 	}
914 	sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP auth result: %s", buf);
915 
916 	if (strstr(buf, "DPP-RESPONSE-PENDING")) {
917 		/* Display own QR code in manual mode */
918 		if (action_type && strcasecmp(action_type, "ManualDPP") == 0 &&
919 		    dpp_display_own_qrcode(dut) < 0) {
920 			send_resp(dut, conn, SIGMA_ERROR,
921 				  "errorCode,Failed to display own QR code");
922 			return -1;
923 		}
924 
925 		/* Wait for the actual result after the peer has scanned the
926 		 * QR Code. */
927 		res = get_wpa_cli_events(dut, ctrl, auth_events,
928 					 buf, buflen);
929 		if (res < 0) {
930 			send_resp(dut, conn, SIGMA_COMPLETE,
931 				  "BootstrapResult,OK,AuthResult,Timeout");
932 			return res;
933 		}
934 
935 		sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP auth result: %s", buf);
936 	} else if (strstr(buf, "DPP-AUTH-INIT-FAILED")) {
937 		send_resp(dut, conn, SIGMA_ERROR,
938 			  "errorCode,Peer did not reply to DPP Authentication Request");
939 		return -1;
940 	}
941 
942 	if (check_mutual) {
943 		if (strstr(buf, "DPP-NOT-COMPATIBLE")) {
944 			send_resp(dut, conn, SIGMA_COMPLETE,
945 				  "BootstrapResult,OK,AuthResult,ROLES_NOT_COMPATIBLE");
946 			return -1;
947 		}
948 
949 		if (!strstr(buf, "DPP-AUTH-DIRECTION")) {
950 			send_resp(dut, conn, SIGMA_ERROR,
951 				  "errorCode,No event for auth direction seen");
952 			return -1;
953 		}
954 
955 		sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP auth direction: %s",
956 				buf);
957 		if (strstr(buf, "mutual=1") == NULL) {
958 			send_resp(dut, conn, SIGMA_ERROR,
959 				  "errorCode,Peer did not use mutual authentication");
960 			return -1;
961 		}
962 	}
963 
964 	return 0;
965 }
966 
967 
968 static enum sigma_cmd_result dpp_automatic_dpp(struct sigma_dut *dut,
969 					       struct sigma_conn *conn,
970 					       struct sigma_cmd *cmd)
971 {
972 	const char *bs = get_param(cmd, "DPPBS");
973 	const char *type = get_param(cmd, "DPPActionType");
974 	const char *auth_role = get_param(cmd, "DPPAuthRole");
975 	const char *prov_role = get_param(cmd, "DPPProvisioningRole");
976 	const char *pkex_code = get_param(cmd, "DPPPKEXCode");
977 	const char *pkex_code_id = get_param(cmd, "DPPPKEXCodeIdentifier");
978 	const char *wait_conn = get_param(cmd, "DPPWaitForConnect");
979 	const char *self_conf = get_param(cmd, "DPPSelfConfigure");
980 	const char *step = get_param(cmd, "DPPStep");
981 	const char *frametype = get_param(cmd, "DPPFrameType");
982 	const char *attr = get_param(cmd, "DPPIEAttribute");
983 	const char *action_type = get_param(cmd, "DPPActionType");
984 	const char *tcp = get_param(cmd, "DPPOverTCP");
985 	const char *nfc_handover = get_param(cmd, "DPPNFCHandover");
986 	const char *role;
987 	const char *netrole = NULL;
988 	const char *val;
989 	const char *conf_role;
990 	int conf_index = -1;
991 	char buf[2000], *pos, *pos2;
992 	char buf2[200];
993 	char conf_ssid[100];
994 	char conf_pass[100];
995 	char pkex_identifier[200];
996 	struct wpa_ctrl *ctrl;
997 	int res;
998 	unsigned int old_timeout;
999 	int own_pkex_id = -1;
1000 	const char *ifname = get_station_ifname(dut);
1001 	const char *auth_events[] = {
1002 		"DPP-AUTH-SUCCESS",
1003 		"DPP-AUTH-INIT-FAILED",
1004 		"DPP-NOT-COMPATIBLE",
1005 		"DPP-RESPONSE-PENDING",
1006 		"DPP-SCAN-PEER-QR-CODE",
1007 		"DPP-AUTH-DIRECTION",
1008 		NULL
1009 	};
1010 	const char *conf_events[] = {
1011 		"DPP-CONF-RECEIVED",
1012 		"DPP-CONF-SENT",
1013 		"DPP-CONF-FAILED",
1014 		NULL
1015 	};
1016 	const char *conn_events[] = {
1017 		"PMKSA-CACHE-ADDED",
1018 		"CTRL-EVENT-CONNECTED",
1019 		NULL
1020 	};
1021 	const char *group_id_str = NULL;
1022 	char group_id[100];
1023 	char conf2[300];
1024 	const char *result;
1025 	int check_mutual = 0;
1026 	int enrollee_ap;
1027 	int enrollee_configurator;
1028 	int force_gas_fragm = 0;
1029 	int not_dpp_akm = 0;
1030 	int akm_use_selector = 0;
1031 	int conn_status;
1032 	int chirp = 0;
1033 	int manual = strcasecmp(type, "ManualDPP") == 0;
1034 	time_t start, now;
1035 
1036 	time(&start);
1037 
1038 	if (!wait_conn)
1039 		wait_conn = "no";
1040 	if (!self_conf)
1041 		self_conf = "no";
1042 
1043 	if (!prov_role) {
1044 		send_resp(dut, conn, SIGMA_ERROR,
1045 			  "errorCode,Missing DPPProvisioningRole");
1046 		return STATUS_SENT_ERROR;
1047 	}
1048 
1049 	val = get_param(cmd, "DPPConfEnrolleeRole");
1050 	if (val) {
1051 		enrollee_ap = strcasecmp(val, "AP") == 0;
1052 		enrollee_configurator = strcasecmp(val, "Configurator") == 0;
1053 	} else {
1054 		enrollee_ap = sigma_dut_is_ap(dut);
1055 		enrollee_configurator = 0;
1056 	}
1057 
1058 	val = get_param(cmd, "DPPNetworkRole");
1059 	if (val) {
1060 		if (strcasecmp(val, "AP") == 0) {
1061 			netrole = "ap";
1062 		} else if (strcasecmp(val, "STA") == 0) {
1063 			netrole = "sta";
1064 		} else if (strcasecmp(val, "Configurator") == 0) {
1065 			netrole = "configurator";
1066 		} else {
1067 			send_resp(dut, conn, SIGMA_ERROR,
1068 				  "errorCode,Unsupported DPPNetworkRole value");
1069 			return STATUS_SENT_ERROR;
1070 		}
1071 	}
1072 
1073 	val = get_param(cmd, "DPPChirp");
1074 	if (val)
1075 		chirp = get_enable_disable(val);
1076 
1077 	if ((step || frametype) && (!step || !frametype)) {
1078 		send_resp(dut, conn, SIGMA_ERROR,
1079 			  "errorCode,Invalid DPPStep,DPPFrameType,DPPIEAttribute combination");
1080 		return STATUS_SENT_ERROR;
1081 	}
1082 
1083 	val = get_param(cmd, "MUDURL");
1084 	if (val) {
1085 		snprintf(buf, sizeof(buf), "SET dpp_mud_url %s", val);
1086 		if (wpa_command(ifname, buf) < 0) {
1087 			send_resp(dut, conn, SIGMA_ERROR,
1088 				  "errorCode,Failed to set MUD URL");
1089 			return STATUS_SENT_ERROR;
1090 		}
1091 	}
1092 
1093 	if (sigma_dut_is_ap(dut)) {
1094 		if (!dut->hostapd_ifname) {
1095 			sigma_dut_print(dut, DUT_MSG_ERROR,
1096 					"hostapd ifname not specified (-j)");
1097 			return ERROR_SEND_STATUS;
1098 		}
1099 		ifname = dut->hostapd_ifname;
1100 
1101 		if (dpp_hostapd_run(dut) < 0) {
1102 			send_resp(dut, conn, SIGMA_ERROR,
1103 				  "errorCode,Failed to start hostapd");
1104 			return STATUS_SENT_ERROR;
1105 		}
1106 	}
1107 
1108 	if (strcasecmp(prov_role, "Configurator") == 0 ||
1109 	    strcasecmp(prov_role, "Both") == 0) {
1110 		if (dut->dpp_conf_id < 0) {
1111 			snprintf(buf, sizeof(buf),
1112 				 "DPP_CONFIGURATOR_ADD curve=%s",
1113 				 dpp_get_curve(cmd, "DPPSigningKeyECC"));
1114 			if (wpa_command_resp(ifname, buf,
1115 					     buf, sizeof(buf)) < 0) {
1116 				send_resp(dut, conn, SIGMA_ERROR,
1117 					  "errorCode,Failed to set up configurator");
1118 				return STATUS_SENT_ERROR;
1119 			}
1120 			dut->dpp_conf_id = atoi(buf);
1121 		}
1122 		if (strcasecmp(prov_role, "Configurator") == 0)
1123 			role = "configurator";
1124 		else
1125 			role = "either";
1126 	} else if (strcasecmp(prov_role, "Enrollee") == 0) {
1127 		role = "enrollee";
1128 	} else {
1129 		send_resp(dut, conn, SIGMA_ERROR,
1130 			  "errorCode,Unknown DPPProvisioningRole");
1131 		return STATUS_SENT_ERROR;
1132 	}
1133 
1134 	pkex_identifier[0] = '\0';
1135 	if (strcasecmp(bs, "PKEX") == 0) {
1136 		if (sigma_dut_is_ap(dut) && dut->ap_channel != 6) {
1137 			/* For now, have to make operating channel match DPP
1138 			 * listen channel. This should be removed once hostapd
1139 			 * has support for DPP listen on non-operating channel.
1140 			 */
1141 			sigma_dut_print(dut, DUT_MSG_INFO,
1142 					"Update hostapd operating channel to match listen needs");
1143 			dut->ap_channel = 6;
1144 
1145 			if (get_driver_type(dut) == DRIVER_OPENWRT) {
1146 				snprintf(buf, sizeof(buf),
1147 					 "iwconfig %s channel %d",
1148 					 dut->hostapd_ifname, dut->ap_channel);
1149 				run_system(dut, buf);
1150 			}
1151 
1152 			if (wpa_command(ifname, "SET channel 6") < 0 ||
1153 			    wpa_command(ifname, "DISABLE") < 0 ||
1154 			    wpa_command(ifname, "ENABLE") < 0) {
1155 				send_resp(dut, conn, SIGMA_ERROR,
1156 					  "errorCode,Failed to update channel");
1157 				return STATUS_SENT_ERROR;
1158 			}
1159 		}
1160 
1161 		if (!pkex_code) {
1162 			send_resp(dut, conn, SIGMA_ERROR,
1163 				  "errorCode,Missing DPPPKEXCode");
1164 			return STATUS_SENT_ERROR;
1165 		}
1166 
1167 		if (pkex_code_id)
1168 			snprintf(pkex_identifier, sizeof(pkex_identifier),
1169 				 "identifier=%s ", pkex_code_id);
1170 
1171 		snprintf(buf, sizeof(buf),
1172 			 "DPP_BOOTSTRAP_GEN type=pkex curve=%s",
1173 			 dpp_get_curve(cmd, "DPPCryptoIdentifier"));
1174 		if (wpa_command_resp(ifname, buf, buf, sizeof(buf)) < 0) {
1175 			send_resp(dut, conn, SIGMA_ERROR,
1176 				  "errorCode,Failed to set up PKEX");
1177 			return STATUS_SENT_ERROR;
1178 		}
1179 		own_pkex_id = atoi(buf);
1180 	}
1181 
1182 	ctrl = open_wpa_mon(ifname);
1183 	if (!ctrl) {
1184 		sigma_dut_print(dut, DUT_MSG_ERROR,
1185 				"Failed to open wpa_supplicant monitor connection");
1186 		return ERROR_SEND_STATUS;
1187 	}
1188 
1189 	old_timeout = dut->default_timeout;
1190 	val = get_param(cmd, "DPPTimeout");
1191 	if (val && atoi(val) > 0) {
1192 		dut->default_timeout = atoi(val);
1193 		sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP timeout: %u",
1194 				dut->default_timeout);
1195 	}
1196 
1197 	val = get_param(cmd, "DPPStatusQuery");
1198 	conn_status = val && strcasecmp(val, "Yes") == 0;
1199 
1200 	conf_ssid[0] = '\0';
1201 	conf_pass[0] = '\0';
1202 	group_id[0] = '\0';
1203 	conf2[0] = '\0';
1204 	if (!enrollee_configurator) {
1205 		val = get_param(cmd, "DPPConfIndex");
1206 		if (val)
1207 			conf_index = atoi(val);
1208 	}
1209 	switch (conf_index) {
1210 	case -1:
1211 		if (enrollee_configurator)
1212 			conf_role = "configurator";
1213 		else
1214 			conf_role = NULL;
1215 		break;
1216 	case 1:
1217 		ascii2hexstr("DPPNET01", buf);
1218 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
1219 		if (res < 0 || res >= sizeof(conf_ssid))
1220 			goto err;
1221 		if (enrollee_ap) {
1222 			conf_role = "ap-dpp";
1223 		} else {
1224 			conf_role = "sta-dpp";
1225 		}
1226 		group_id_str = "DPPGROUP_DPP_INFRA";
1227 		break;
1228 	case 2:
1229 		ascii2hexstr("DPPNET01", buf);
1230 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
1231 		if (res < 0 || res >= sizeof(conf_ssid))
1232 			goto err;
1233 		snprintf(conf_pass, sizeof(conf_pass),
1234 			 "psk=10506e102ad1e7f95112f6b127675bb8344dacacea60403f3fa4055aec85b0fc");
1235 		if (enrollee_ap)
1236 			conf_role = "ap-psk";
1237 		else
1238 			conf_role = "sta-psk";
1239 		break;
1240 	case 3:
1241 		ascii2hexstr("DPPNET01", buf);
1242 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
1243 		if (res < 0 || res >= sizeof(conf_ssid))
1244 			goto err;
1245 		ascii2hexstr("ThisIsDppPassphrase", buf);
1246 		res = snprintf(conf_pass, sizeof(conf_pass), "pass=%s", buf);
1247 		if (res < 0 || res >= sizeof(conf_pass))
1248 			goto err;
1249 		if (enrollee_ap)
1250 			conf_role = "ap-psk";
1251 		else
1252 			conf_role = "sta-psk";
1253 		break;
1254 	case 4:
1255 		ascii2hexstr("DPPNET01", buf);
1256 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
1257 		if (res < 0 || res >= sizeof(conf_ssid))
1258 			goto err;
1259 		if (enrollee_ap) {
1260 			conf_role = "ap-dpp";
1261 		} else {
1262 			conf_role = "sta-dpp";
1263 		}
1264 		group_id_str = "DPPGROUP_DPP_INFRA2";
1265 		break;
1266 	case 5:
1267 		ascii2hexstr("DPPNET01", buf);
1268 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
1269 		if (res < 0 || res >= sizeof(conf_ssid))
1270 			goto err;
1271 		ascii2hexstr("ThisIsDppPassphrase", buf);
1272 		res = snprintf(conf_pass, sizeof(conf_pass), "pass=%s", buf);
1273 		if (res < 0 || res >= sizeof(conf_pass))
1274 			goto err;
1275 		if (enrollee_ap)
1276 			conf_role = "ap-sae";
1277 		else
1278 			conf_role = "sta-sae";
1279 		break;
1280 	case 6:
1281 		ascii2hexstr("DPPNET01", buf);
1282 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
1283 		if (res < 0 || res >= sizeof(conf_ssid))
1284 			goto err;
1285 		ascii2hexstr("ThisIsDppPassphrase", buf);
1286 		res = snprintf(conf_pass, sizeof(conf_pass), "pass=%s", buf);
1287 		if (res < 0 || res >= sizeof(conf_pass))
1288 			goto err;
1289 		if (enrollee_ap)
1290 			conf_role = "ap-psk-sae";
1291 		else
1292 			conf_role = "sta-psk-sae";
1293 		break;
1294 	case 7:
1295 		ascii2hexstr("DPPNET01", buf);
1296 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
1297 		if (res < 0 || res >= sizeof(conf_ssid))
1298 			goto err;
1299 		if (enrollee_ap) {
1300 			conf_role = "ap-dpp";
1301 		} else {
1302 			conf_role = "sta-dpp";
1303 		}
1304 		group_id_str = "DPPGROUP_DPP_INFRA";
1305 		force_gas_fragm = 1;
1306 		break;
1307 	case 8:
1308 	case 9:
1309 		ascii2hexstr("DPPNET01", buf);
1310 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
1311 		if (res < 0 || res >= sizeof(conf_ssid))
1312 			goto err;
1313 		ascii2hexstr("This_is_legacy_password", buf);
1314 		res = snprintf(conf_pass, sizeof(conf_pass), "pass=%s", buf);
1315 		if (res < 0 || res >= sizeof(conf_pass))
1316 			goto err;
1317 		if (enrollee_ap) {
1318 			conf_role = "ap-dpp+psk+sae";
1319 		} else {
1320 			conf_role = "sta-dpp+psk+sae";
1321 		}
1322 		group_id_str = "DPPGROUP_DPP_INFRA1";
1323 		if (conf_index == 9)
1324 			akm_use_selector = 1;
1325 		break;
1326 	case 10:
1327 		ascii2hexstr("DPPNET01", buf);
1328 		res = snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
1329 		if (res < 0 || res >= sizeof(conf_ssid))
1330 			goto err;
1331 		if (enrollee_ap)
1332 			conf_role = "ap-dpp";
1333 		else
1334 			conf_role = "sta-dpp";
1335 		group_id_str = "DPPGROUP_DPP_INFRA1";
1336 		ascii2hexstr("DPPNET02", buf);
1337 		ascii2hexstr("This_is_legacy_password", buf2);
1338 		res = snprintf(conf2, sizeof(conf2),
1339 			       " @CONF-OBJ-SEP@ conf=%s-dpp+psk+sae ssid=%s pass=%s group_id=DPPGROUP_DPP_INFRA2",
1340 			       enrollee_ap ? "ap" : "sta", buf, buf2);
1341 		if (res < 0 || res >= sizeof(conf2))
1342 			goto err;
1343 		break;
1344 	default:
1345 		send_resp(dut, conn, SIGMA_ERROR,
1346 			  "errorCode,Unsupported DPPConfIndex");
1347 		goto out;
1348 	}
1349 
1350 	if (group_id_str)
1351 		snprintf(group_id, sizeof(group_id), " group_id=%s",
1352 			 group_id_str);
1353 
1354 	if (force_gas_fragm) {
1355 		char spaces[1500];
1356 
1357 		memset(spaces, ' ', sizeof(spaces));
1358 		spaces[sizeof(spaces) - 1] = '\0';
1359 
1360 		snprintf(buf, sizeof(buf),
1361 			 "SET dpp_discovery_override {\"ssid\":\"DPPNET01\"}%s",
1362 			 spaces);
1363 		if (wpa_command(ifname, buf) < 0) {
1364 			send_resp(dut, conn, SIGMA_ERROR,
1365 				  "errorCode,Failed to set discovery override");
1366 			goto out;
1367 		}
1368 	}
1369 
1370 	if (step) {
1371 		int test;
1372 
1373 		test = dpp_get_test(step, frametype, attr);
1374 		if (test <= 0) {
1375 			send_resp(dut, conn, SIGMA_ERROR,
1376 				  "errorCode,Unsupported DPPStep/DPPFrameType/DPPIEAttribute");
1377 			goto out;
1378 		}
1379 
1380 		snprintf(buf, sizeof(buf), "SET dpp_test %d", test);
1381 		if (wpa_command(ifname, buf) < 0) {
1382 			send_resp(dut, conn, SIGMA_ERROR,
1383 				  "errorCode,Failed to set dpp_test");
1384 			goto out;
1385 		}
1386 	} else {
1387 		wpa_command(ifname, "SET dpp_test 0");
1388 	}
1389 
1390 	if (strcasecmp(self_conf, "Yes") == 0) {
1391 		if (strcasecmp(prov_role, "Configurator") != 0) {
1392 			send_resp(dut, conn, SIGMA_ERROR,
1393 				  "errorCode,Invalid DPPSelfConfigure use - only allowed for Configurator role");
1394 			goto out;
1395 		}
1396 		if (!conf_role) {
1397 			send_resp(dut, conn, SIGMA_ERROR,
1398 				  "errorCode,Missing DPPConfIndex");
1399 			goto out;
1400 		}
1401 
1402 		snprintf(buf, sizeof(buf),
1403 			 "DPP_CONFIGURATOR_SIGN  conf=%s %s %s configurator=%d",
1404 			 conf_role, conf_ssid, conf_pass, dut->dpp_conf_id);
1405 		if (wpa_command(ifname, buf) < 0) {
1406 			send_resp(dut, conn, SIGMA_ERROR,
1407 				  "errorCode,Failed to initiate DPP self-configuration");
1408 			goto out;
1409 		}
1410 		if (sigma_dut_is_ap(dut))
1411 			goto update_ap;
1412 		goto wait_connect;
1413 	} else if (manual && strcasecmp(bs, "NFC") == 0) {
1414 		const char *val = get_param(cmd, "DPPNFCInit");
1415 		int init = val && atoi(val) > 0;
1416 		pid_t pid;
1417 		int pid_status;
1418 		int enrollee = 0;
1419 		const char *tx_rx_events[] = { "DPP-TX", "DPP-RX", NULL };
1420 
1421 		if (strcasecmp(prov_role, "Configurator") == 0 ||
1422 		    strcasecmp(prov_role, "Both") == 0) {
1423 			if (!conf_role) {
1424 				send_resp(dut, conn, SIGMA_ERROR,
1425 					  "errorCode,Missing DPPConfIndex");
1426 				goto out;
1427 			}
1428 			snprintf(buf, sizeof(buf),
1429 				 "SET dpp_configurator_params  conf=%s %s %s configurator=%d%s%s%s%s",
1430 				 conf_role, conf_ssid, conf_pass,
1431 				 dut->dpp_conf_id, group_id,
1432 				 akm_use_selector ? " akm_use_selector=1" : "",
1433 				 conn_status ? " conn_status=1" : "", conf2);
1434 			if (wpa_command(ifname, buf) < 0) {
1435 				send_resp(dut, conn, SIGMA_ERROR,
1436 					  "errorCode,Failed to set configurator parameters");
1437 				goto out;
1438 			}
1439 			snprintf(buf, sizeof(buf),
1440 				 "conf=%s %s %s configurator=%d%s%s%s%s",
1441 				 conf_role, conf_ssid, conf_pass,
1442 				 dut->dpp_conf_id, group_id,
1443 				 akm_use_selector ? " akm_use_selector=1" : "",
1444 				 conn_status ? " conn_status=1" : "", conf2);
1445 		} else {
1446 			buf[0] = '\0';
1447 			enrollee = 1;
1448 		}
1449 
1450 		run_system(dut, "killall dpp-nfc.py");
1451 		sigma_dut_print(dut, DUT_MSG_INFO, "Manual NFC operation");
1452 		if (!file_exists("dpp-nfc.py")) {
1453 			send_resp(dut, conn, SIGMA_ERROR,
1454 				  "errorCode,dpp-nfc.py not found");
1455 			goto out;
1456 		}
1457 
1458 		pid = fork();
1459 		if (pid < 0) {
1460 			perror("fork");
1461 			send_resp(dut, conn, SIGMA_ERROR,
1462 				  "errorCode,fork() failed");
1463 			goto out;
1464 		}
1465 
1466 		if (pid == 0) {
1467 			char * argv[] = { "dpp-nfc.py",
1468 					  "--only-one", "--no-input",
1469 					  "-i", (char *) ifname,
1470 					  "--ctrl", sigma_wpas_ctrl,
1471 					  enrollee ? "--enrollee" :
1472 					  "--configurator",
1473 					  "--config-params", buf,
1474 					  init ? "-I" : NULL,
1475 					  NULL };
1476 
1477 			execv("./dpp-nfc.py", argv);
1478 			perror("execv");
1479 			exit(0);
1480 			return -1;
1481 		}
1482 
1483 		usleep(300000);
1484 		for (;;) {
1485 			if (waitpid(pid, &pid_status, WNOHANG) > 0) {
1486 				sigma_dut_print(dut, DUT_MSG_DEBUG,
1487 						"dpp-nfc.py exited");
1488 				break;
1489 			}
1490 
1491 			time(&now);
1492 			if ((unsigned int) (now - start) >=
1493 			    dut->default_timeout) {
1494 				sigma_dut_print(dut, DUT_MSG_DEBUG,
1495 						"dpp-nfc.py did not exit within timeout - stop it");
1496 				kill(pid, SIGTERM);
1497 				waitpid(pid, &pid_status, 0);
1498 				send_resp(dut, conn, SIGMA_ERROR,
1499 					  "errorCode,dpp-nfc.py did not complete within timeout");
1500 				goto out;
1501 			}
1502 
1503 			old_timeout = dut->default_timeout;
1504 			dut->default_timeout = 2;
1505 
1506 			res = get_wpa_cli_events(dut, ctrl, tx_rx_events,
1507 						buf, sizeof(buf));
1508 			dut->default_timeout = old_timeout;
1509 			if (res >= 0) {
1510 				sigma_dut_print(dut, DUT_MSG_DEBUG,
1511 						"DPP exchange started");
1512 				usleep(500000);
1513 				kill(pid, SIGTERM);
1514 				waitpid(pid, &pid_status, 0);
1515 				break;
1516 			}
1517 		}
1518 	} else if ((nfc_handover &&
1519 		    strcasecmp(nfc_handover, "Negotiated_Requestor") == 0) ||
1520 		   ((!nfc_handover ||
1521 		     strcasecmp(nfc_handover, "Static") == 0) &&
1522 		    auth_role && strcasecmp(auth_role, "Initiator") == 0)) {
1523 		char own_txt[20];
1524 		int dpp_peer_bootstrap = -1;
1525 		char neg_freq[30];
1526 
1527 		val = get_param(cmd, "DPPAuthDirection");
1528 		check_mutual = val && strcasecmp(val, "Mutual") == 0;
1529 
1530 		neg_freq[0] = '\0';
1531 		val = get_param(cmd, "DPPSubsequentChannel");
1532 		if (val) {
1533 			int opclass, channel, freq;
1534 
1535 			opclass = atoi(val);
1536 			val = strchr(val, '/');
1537 			if (opclass == 0 || !val) {
1538 				send_resp(dut, conn, SIGMA_ERROR,
1539 					  "errorCode,Invalid DPPSubsequentChannel");
1540 				goto out;
1541 			}
1542 			val++;
1543 			channel = atoi(val);
1544 
1545 			/* Ignoring opclass for now; could use it here for more
1546 			 * robust frequency determination. */
1547 			freq = channel_to_freq(dut, channel);
1548 			if (!freq) {
1549 				send_resp(dut, conn, SIGMA_ERROR,
1550 					  "errorCode,Unsupported DPPSubsequentChannel channel");
1551 				goto out;
1552 			}
1553 			snprintf(neg_freq, sizeof(neg_freq), " neg_freq=%d",
1554 				 freq);
1555 		}
1556 
1557 		if (strcasecmp(bs, "QR") == 0) {
1558 			if (!dut->dpp_peer_uri) {
1559 				send_resp(dut, conn, SIGMA_ERROR,
1560 					  "errorCode,Missing peer bootstrapping info");
1561 				goto out;
1562 			}
1563 
1564 			snprintf(buf, sizeof(buf), "DPP_QR_CODE %s",
1565 				 dut->dpp_peer_uri);
1566 			if (wpa_command_resp(ifname, buf, buf,
1567 					     sizeof(buf)) < 0 ||
1568 			    strncmp(buf, "FAIL", 4) == 0) {
1569 				send_resp(dut, conn, SIGMA_ERROR,
1570 					  "errorCode,Failed to parse URI");
1571 				goto out;
1572 			}
1573 			dpp_peer_bootstrap = atoi(buf);
1574 		} else if (strcasecmp(bs, "NFC") == 0 && nfc_handover &&
1575 			   strcasecmp(nfc_handover, "Static") == 0) {
1576 			if (!dut->dpp_peer_uri) {
1577 				send_resp(dut, conn, SIGMA_ERROR,
1578 					  "errorCode,Missing peer bootstrapping info");
1579 				goto out;
1580 			}
1581 
1582 			snprintf(buf, sizeof(buf), "DPP_NFC_URI %s",
1583 				 dut->dpp_peer_uri);
1584 			if (wpa_command_resp(ifname, buf,
1585 					     buf, sizeof(buf)) < 0 ||
1586 			    strncmp(buf, "FAIL", 4) == 0) {
1587 				send_resp(dut, conn, SIGMA_ERROR,
1588 					  "errorCode,Failed to process URI from NFC Tag");
1589 				goto out;
1590 			}
1591 			dpp_peer_bootstrap = atoi(buf);
1592 		} else if (strcasecmp(bs, "NFC") == 0) {
1593 			if (!dut->dpp_peer_uri) {
1594 				send_resp(dut, conn, SIGMA_ERROR,
1595 					  "errorCode,Missing peer bootstrapping info");
1596 				goto out;
1597 			}
1598 			if (dut->dpp_local_bootstrap < 0) {
1599 				send_resp(dut, conn, SIGMA_ERROR,
1600 					  "errorCode,Missing own bootstrapping info");
1601 				goto out;
1602 			}
1603 
1604 			snprintf(buf, sizeof(buf),
1605 				 "DPP_NFC_HANDOVER_SEL own=%d uri=%s",
1606 				 dut->dpp_local_bootstrap, dut->dpp_peer_uri);
1607 			if (wpa_command_resp(ifname, buf,
1608 					     buf, sizeof(buf)) < 0 ||
1609 			    strncmp(buf, "FAIL", 4) == 0) {
1610 				send_resp(dut, conn, SIGMA_ERROR,
1611 					  "errorCode,Failed to process NFC Handover Select");
1612 				goto out;
1613 			}
1614 			dpp_peer_bootstrap = atoi(buf);
1615 		}
1616 
1617 		if (dut->dpp_local_bootstrap >= 0)
1618 			snprintf(own_txt, sizeof(own_txt), " own=%d",
1619 				 dut->dpp_local_bootstrap);
1620 		else
1621 			own_txt[0] = '\0';
1622 		if (chirp) {
1623 			int freq = 2437; /* default: channel 6 */
1624 
1625 			val = get_param(cmd, "DPPChirpChannel");
1626 			if (val) {
1627 				freq = channel_to_freq(dut, atoi(val));
1628 				if (!freq) {
1629 					send_resp(dut, conn, SIGMA_ERROR,
1630 						  "errorCode,Unsupported DPPChirpChannel channel");
1631 					goto out;
1632 				}
1633 			}
1634 
1635 			if (strcasecmp(prov_role, "Configurator") == 0 ||
1636 			    strcasecmp(prov_role, "Both") == 0) {
1637 				if (!conf_role) {
1638 					send_resp(dut, conn, SIGMA_ERROR,
1639 						  "errorCode,Missing DPPConfIndex");
1640 					goto out;
1641 				}
1642 				snprintf(buf, sizeof(buf),
1643 					 "SET dpp_configurator_params  conf=%s %s %s configurator=%d%s%s%s%s",
1644 					 conf_role, conf_ssid, conf_pass,
1645 					 dut->dpp_conf_id, group_id,
1646 					 akm_use_selector ?
1647 					 " akm_use_selector=1" : "",
1648 					 conn_status ? " conn_status=1" : "",
1649 					 conf2);
1650 				if (wpa_command(ifname, buf) < 0) {
1651 					send_resp(dut, conn, SIGMA_ERROR,
1652 						  "errorCode,Failed to set configurator parameters");
1653 					goto out;
1654 				}
1655 			}
1656 
1657 			if (tcp && strcasecmp(tcp, "yes") == 0) {
1658 				snprintf(buf, sizeof(buf),
1659 					 "DPP_CONTROLLER_START");
1660 			} else {
1661 				snprintf(buf, sizeof(buf),
1662 					 "DPP_LISTEN %d role=%s%s%s",
1663 					 freq, role,
1664 					 netrole ? " netrole=" : "",
1665 					 netrole ? netrole : "");
1666 			}
1667 		} else if ((strcasecmp(bs, "QR") == 0 ||
1668 			    strcasecmp(bs, "NFC") == 0) &&
1669 			   (strcasecmp(prov_role, "Configurator") == 0 ||
1670 			    strcasecmp(prov_role, "Both") == 0)) {
1671 			if (!conf_role) {
1672 				send_resp(dut, conn, SIGMA_ERROR,
1673 					  "errorCode,Missing DPPConfIndex");
1674 				goto out;
1675 			}
1676 			snprintf(buf, sizeof(buf),
1677 				 "DPP_AUTH_INIT peer=%d%s role=%s%s%s conf=%s %s %s configurator=%d%s%s%s%s%s%s%s",
1678 				 dpp_peer_bootstrap, own_txt, role,
1679 				 netrole ? " netrole=" : "",
1680 				 netrole ? netrole : "",
1681 				 conf_role, conf_ssid, conf_pass,
1682 				 dut->dpp_conf_id, neg_freq, group_id,
1683 				 akm_use_selector ? " akm_use_selector=1" : "",
1684 				 conn_status ? " conn_status=1" : "",
1685 				 tcp ? " tcp_addr=" : "",
1686 				 tcp ? tcp : "",
1687 				 conf2);
1688 		} else if (tcp && (strcasecmp(bs, "QR") == 0 ||
1689 				   strcasecmp(bs, "NFC") == 0)) {
1690 			snprintf(buf, sizeof(buf),
1691 				 "DPP_AUTH_INIT peer=%d%s role=%s%s%s tcp_addr=%s%s%s",
1692 				 dpp_peer_bootstrap, own_txt, role,
1693 				 netrole ? " netrole=" : "",
1694 				 netrole ? netrole : "",
1695 				 tcp, neg_freq, group_id);
1696 		} else if (strcasecmp(bs, "QR") == 0 ||
1697 			   strcasecmp(bs, "NFC") == 0) {
1698 			snprintf(buf, sizeof(buf),
1699 				 "DPP_AUTH_INIT peer=%d%s role=%s%s%s%s%s",
1700 				 dpp_peer_bootstrap, own_txt, role,
1701 				 netrole ? " netrole=" : "",
1702 				 netrole ? netrole : "",
1703 				 neg_freq, group_id);
1704 		} else if (strcasecmp(bs, "PKEX") == 0 &&
1705 			   (strcasecmp(prov_role, "Configurator") == 0 ||
1706 			    strcasecmp(prov_role, "Both") == 0)) {
1707 			if (!conf_role) {
1708 				send_resp(dut, conn, SIGMA_ERROR,
1709 					  "errorCode,Missing DPPConfIndex");
1710 				goto out;
1711 			}
1712 			snprintf(buf, sizeof(buf),
1713 				 "DPP_PKEX_ADD own=%d init=1 role=%s conf=%s %s %s configurator=%d %scode=%s",
1714 				 own_pkex_id, role, conf_role,
1715 				 conf_ssid, conf_pass, dut->dpp_conf_id,
1716 				 pkex_identifier, pkex_code);
1717 		} else if (strcasecmp(bs, "PKEX") == 0) {
1718 			snprintf(buf, sizeof(buf),
1719 				 "DPP_PKEX_ADD own=%d init=1 role=%s %scode=%s",
1720 				 own_pkex_id, role, pkex_identifier, pkex_code);
1721 		} else {
1722 			send_resp(dut, conn, SIGMA_ERROR,
1723 				  "errorCode,Unsupported DPPBS");
1724 			goto out;
1725 		}
1726 		if (wpa_command(ifname, buf) < 0) {
1727 			send_resp(dut, conn, SIGMA_ERROR,
1728 				  "errorCode,Failed to initiate DPP authentication");
1729 			goto out;
1730 		}
1731 	} else if ((nfc_handover &&
1732 		    strcasecmp(nfc_handover, "Negotiated_Selector") == 0) ||
1733 		   ((!nfc_handover ||
1734 		     strcasecmp(nfc_handover, "Static") == 0) &&
1735 		    auth_role && strcasecmp(auth_role, "Responder") == 0)) {
1736 		const char *delay_qr_resp;
1737 		int mutual;
1738 		int freq = 2462; /* default: channel 11 */
1739 
1740 		if (sigma_dut_is_ap(dut) && dut->hostapd_running &&
1741 		    dut->ap_oper_chn)
1742 			freq = channel_to_freq(dut, dut->ap_channel);
1743 
1744 		if (sigma_dut_is_ap(dut) && dpp_hostapd_beacon(dut) < 0) {
1745 			send_resp(dut, conn, SIGMA_ERROR,
1746 				  "errorCode,Failed to start AP mode listen");
1747 			goto out;
1748 		}
1749 
1750 		if (strcasecmp(bs, "PKEX") == 0) {
1751 			/* default: channel 6 for PKEX */
1752 			freq = 2437;
1753 		}
1754 
1755 		delay_qr_resp = get_param(cmd, "DPPDelayQRResponse");
1756 
1757 		val = get_param(cmd, "DPPAuthDirection");
1758 		mutual = val && strcasecmp(val, "Mutual") == 0;
1759 
1760 		val = get_param(cmd, "DPPListenChannel");
1761 		if (val) {
1762 			freq = channel_to_freq(dut, atoi(val));
1763 			if (freq == 0) {
1764 				send_resp(dut, conn, SIGMA_ERROR,
1765 					  "errorCode,Unsupported DPPListenChannel value");
1766 				goto out;
1767 			}
1768 		}
1769 
1770 		if (strcasecmp(bs, "NFC") == 0 && nfc_handover &&
1771 		    strcasecmp(nfc_handover, "Static") == 0) {
1772 			/* No steps needed here - waiting for peer to initiate
1773 			 * once it reads the URI from the NFC Tag */
1774 		} else if (strcasecmp(bs, "NFC") == 0) {
1775 			if (!dut->dpp_peer_uri) {
1776 				send_resp(dut, conn, SIGMA_ERROR,
1777 					  "errorCode,Missing peer bootstrapping info");
1778 				goto out;
1779 			}
1780 			if (dut->dpp_local_bootstrap < 0) {
1781 				send_resp(dut, conn, SIGMA_ERROR,
1782 					  "errorCode,Missing own bootstrapping info");
1783 				goto out;
1784 			}
1785 
1786 			snprintf(buf, sizeof(buf),
1787 				 "DPP_NFC_HANDOVER_REQ own=%d uri=%s",
1788 				 dut->dpp_local_bootstrap, dut->dpp_peer_uri);
1789 			if (wpa_command(ifname, buf) < 0) {
1790 				send_resp(dut, conn, SIGMA_ERROR,
1791 					  "errorCode,Failed to process NFC Handover Request");
1792 				goto out;
1793 			}
1794 
1795 			snprintf(buf, sizeof(buf), "DPP_BOOTSTRAP_INFO %d",
1796 				 dut->dpp_local_bootstrap);
1797 			if (wpa_command_resp(ifname, buf,
1798 					     buf, sizeof(buf)) < 0 ||
1799 			    strncmp(buf, "FAIL", 4) == 0) {
1800 				send_resp(dut, conn, SIGMA_ERROR,
1801 					  "errorCode,Failed to get bootstrap information");
1802 				goto out;
1803 			}
1804 			pos = buf;
1805 			while (pos) {
1806 				pos2 = strchr(pos, '\n');
1807 				if (pos2)
1808 					*pos2 = '\0';
1809 				if (strncmp(pos, "use_freq=", 9) == 0) {
1810 					freq = atoi(pos + 9);
1811 					sigma_dut_print(dut, DUT_MSG_DEBUG,
1812 							"DPP negotiation frequency from NFC handover: %d MHz",
1813 							freq);
1814 					break;
1815 				}
1816 
1817 				if (!pos2)
1818 					break;
1819 				pos = pos2 + 1;
1820 			}
1821 		} else if (!delay_qr_resp && dut->dpp_peer_uri) {
1822 			snprintf(buf, sizeof(buf), "DPP_QR_CODE %s",
1823 				 dut->dpp_peer_uri);
1824 			if (wpa_command_resp(ifname, buf, buf,
1825 					     sizeof(buf)) < 0) {
1826 				send_resp(dut, conn, SIGMA_ERROR,
1827 					  "errorCode,Failed to parse URI");
1828 				goto out;
1829 			}
1830 		}
1831 
1832 		if (strcasecmp(prov_role, "Configurator") == 0) {
1833 			if (!conf_role) {
1834 				send_resp(dut, conn, SIGMA_ERROR,
1835 					  "errorCode,Missing DPPConfIndex");
1836 				goto out;
1837 			}
1838 			snprintf(buf, sizeof(buf),
1839 				 "SET dpp_configurator_params  conf=%s %s %s configurator=%d%s%s%s%s",
1840 				 conf_role, conf_ssid, conf_pass,
1841 				 dut->dpp_conf_id, group_id,
1842 				 akm_use_selector ? " akm_use_selector=1" : "",
1843 				 conn_status ? " conn_status=1" : "",
1844 				 conf2);
1845 			if (wpa_command(ifname, buf) < 0) {
1846 				send_resp(dut, conn, SIGMA_ERROR,
1847 					  "errorCode,Failed to set configurator parameters");
1848 				goto out;
1849 			}
1850 		}
1851 		if (strcasecmp(bs, "PKEX") == 0) {
1852 			snprintf(buf, sizeof(buf),
1853 				 "DPP_PKEX_ADD own=%d role=%s %scode=%s",
1854 				 own_pkex_id, role, pkex_identifier, pkex_code);
1855 			if (wpa_command(ifname, buf) < 0) {
1856 				send_resp(dut, conn, SIGMA_ERROR,
1857 					  "errorCode,Failed to configure DPP PKEX");
1858 				goto out;
1859 			}
1860 		}
1861 
1862 		if (chirp) {
1863 			snprintf(buf, sizeof(buf),
1864 				 "DPP_CHIRP own=%d iter=10 listen=%d",
1865 				 dut->dpp_local_bootstrap, freq);
1866 		} else if (tcp && strcasecmp(tcp, "yes") == 0) {
1867 			snprintf(buf, sizeof(buf), "DPP_CONTROLLER_START");
1868 		} else {
1869 			snprintf(buf, sizeof(buf),
1870 				 "DPP_LISTEN %d role=%s%s%s%s",
1871 				 freq, role,
1872 				 (strcasecmp(bs, "QR") == 0 && mutual) ?
1873 				 " qr=mutual" : "",
1874 				 netrole ? " netrole=" : "",
1875 				 netrole ? netrole : "");
1876 		}
1877 		if (wpa_command(ifname, buf) < 0) {
1878 			send_resp(dut, conn, SIGMA_ERROR,
1879 				  "errorCode,Failed to start DPP listen/chirp");
1880 			goto out;
1881 		}
1882 
1883 		if (!(tcp && strcasecmp(tcp, "yes") == 0) &&
1884 		    get_driver_type(dut) == DRIVER_OPENWRT) {
1885 			snprintf(buf, sizeof(buf), "iwconfig %s channel %d",
1886 				 dut->hostapd_ifname, freq_to_channel(freq));
1887 			run_system(dut, buf);
1888 		}
1889 
1890 		if (delay_qr_resp && mutual && dut->dpp_peer_uri) {
1891 			int wait_time = atoi(delay_qr_resp);
1892 
1893 			res = get_wpa_cli_events(dut, ctrl, auth_events,
1894 						 buf, sizeof(buf));
1895 			if (res < 0) {
1896 				send_resp(dut, conn, SIGMA_COMPLETE,
1897 					  "BootstrapResult,OK,AuthResult,Timeout");
1898 				goto out;
1899 			}
1900 			sigma_dut_print(dut, DUT_MSG_DEBUG,
1901 					"DPP auth result: %s", buf);
1902 			if (strstr(buf, "DPP-SCAN-PEER-QR-CODE") == NULL) {
1903 				send_resp(dut, conn, SIGMA_ERROR,
1904 					  "errorCode,No scan request for peer QR Code seen");
1905 				goto out;
1906 			}
1907 			sigma_dut_print(dut, DUT_MSG_INFO,
1908 					"Waiting %d second(s) before processing peer URI",
1909 					wait_time);
1910 			sleep(wait_time);
1911 
1912 			snprintf(buf, sizeof(buf), "DPP_QR_CODE %s",
1913 				 dut->dpp_peer_uri);
1914 			if (wpa_command_resp(ifname, buf, buf,
1915 					     sizeof(buf)) < 0) {
1916 				send_resp(dut, conn, SIGMA_ERROR,
1917 					  "errorCode,Failed to parse URI");
1918 				goto out;
1919 			}
1920 		} else if (mutual && action_type &&
1921 			   strcasecmp(action_type, "ManualDPP") == 0) {
1922 			res = get_wpa_cli_events(dut, ctrl, auth_events,
1923 						 buf, sizeof(buf));
1924 			if (res < 0) {
1925 				send_resp(dut, conn, SIGMA_COMPLETE,
1926 					  "BootstrapResult,OK,AuthResult,Timeout");
1927 				goto out;
1928 			}
1929 			sigma_dut_print(dut, DUT_MSG_DEBUG,
1930 					"DPP auth result: %s", buf);
1931 			if (strstr(buf, "DPP-NOT-COMPATIBLE")) {
1932 			    send_resp(dut, conn, SIGMA_COMPLETE,
1933 				      "BootstrapResult,OK,AuthResult,ROLES_NOT_COMPATIBLE");
1934 			    goto out;
1935 			}
1936 
1937 			if (strstr(buf, "DPP-SCAN-PEER-QR-CODE") == NULL) {
1938 				send_resp(dut, conn, SIGMA_ERROR,
1939 					  "errorCode,No scan request for peer QR Code seen");
1940 				goto out;
1941 			}
1942 
1943 			if (dpp_scan_peer_qrcode(dut) < 0) {
1944 				send_resp(dut, conn, SIGMA_ERROR,
1945 					  "errorCode,Failed to scan peer QR Code");
1946 				goto out;
1947 			}
1948 
1949 			snprintf(buf, sizeof(buf), "DPP_QR_CODE %s",
1950 				 dut->dpp_peer_uri);
1951 			if (wpa_command_resp(ifname, buf, buf,
1952 					     sizeof(buf)) < 0) {
1953 				send_resp(dut, conn, SIGMA_ERROR,
1954 					  "errorCode,Failed to parse URI");
1955 				goto out;
1956 			}
1957 		}
1958 	} else {
1959 		send_resp(dut, conn, SIGMA_ERROR,
1960 			  "errorCode,Unknown DPPAuthRole");
1961 		goto out;
1962 	}
1963 
1964 	if (step && strcasecmp(step, "Timeout") == 0) {
1965 		result = "errorCode,Unexpected state";
1966 
1967 		if (strcasecmp(frametype, "PKEXExchangeResponse") == 0) {
1968 			if (dpp_wait_rx(dut, ctrl, 8, -1) < 0)
1969 				result = "BootstrapResult,Timeout";
1970 			else
1971 				result = "BootstrapResult,Errorsent";
1972 		}
1973 
1974 		if (strcasecmp(frametype, "PKEXCRRequest") == 0) {
1975 			if (dpp_wait_rx(dut, ctrl, 9, -1) < 0)
1976 				result = "BootstrapResult,Timeout";
1977 			else
1978 				result = "BootstrapResult,Errorsent";
1979 		}
1980 
1981 		if (strcasecmp(frametype, "PKEXCRResponse") == 0) {
1982 			if (dpp_wait_rx(dut, ctrl, 10, -1) < 0)
1983 				result = "BootstrapResult,Timeout";
1984 			else
1985 				result = "BootstrapResult,Errorsent";
1986 		}
1987 
1988 		if (strcasecmp(frametype, "AuthenticationRequest") == 0) {
1989 			if (dpp_wait_rx(dut, ctrl, 0, -1) < 0)
1990 				result = "BootstrapResult,OK,AuthResult,Timeout";
1991 			else
1992 				result = "BootstrapResult,OK,AuthResult,Errorsent";
1993 		}
1994 
1995 		if (strcasecmp(frametype, "AuthenticationResponse") == 0) {
1996 			if (dpp_wait_rx(dut, ctrl, 1, -1) < 0)
1997 				result = "BootstrapResult,OK,AuthResult,Timeout";
1998 			else
1999 				result = "BootstrapResult,OK,AuthResult,Errorsent";
2000 		}
2001 
2002 		if (strcasecmp(frametype, "AuthenticationConfirm") == 0) {
2003 			if (auth_role &&
2004 			    strcasecmp(auth_role, "Initiator") == 0) {
2005 				/* This special case of DPPStep,Timeout with
2006 				 * DPPFrameType,AuthenticationConfirm on an
2007 				 * Initiator is used to cover need for stopping
2008 				 * the Initiator/Enrollee from sending out
2009 				 * Configuration Request message. */
2010 				if (strcasecmp(prov_role, "Enrollee") != 0) {
2011 					send_resp(dut, conn, SIGMA_ERROR,
2012 						  "errorCode,Unexpected use of timeout after AuthenticationConfirm TX in Configurator role");
2013 					goto out;
2014 				}
2015 				if (check_mutual &&
2016 				    dpp_process_auth_response(
2017 					    dut, conn, ctrl, auth_events,
2018 					    action_type, check_mutual,
2019 					    buf, sizeof(buf)) < 0)
2020 					goto out;
2021 				if (dpp_wait_tx_status(dut, ctrl, 2) < 0)
2022 					result = "BootstrapResult,OK,AuthResult,Timeout";
2023 				else
2024 					result = "BootstrapResult,OK,AuthResult,Errorsent,LastFrameReceived,AuthenticationResponse";
2025 			} else {
2026 				if (dpp_wait_rx(dut, ctrl, 2, -1) < 0)
2027 					result = "BootstrapResult,OK,AuthResult,Timeout";
2028 				else
2029 					result = "BootstrapResult,OK,AuthResult,Errorsent,LastFrameReceived,AuthenticationConfirm";
2030 			}
2031 		}
2032 
2033 		if (strcasecmp(frametype, "ConfigurationRequest") == 0) {
2034 			if (get_wpa_cli_event(dut, ctrl, "DPP-CONF-FAILED",
2035 					      buf, sizeof(buf)) < 0)
2036 				result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Timeout";
2037 			else
2038 				result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Errorsent";
2039 		}
2040 
2041 		send_resp(dut, conn, SIGMA_COMPLETE, result);
2042 		goto out;
2043 	}
2044 
2045 	if (frametype && strcasecmp(frametype, "PKEXExchangeRequest") == 0) {
2046 		if (dpp_wait_tx_status(dut, ctrl, 7) < 0)
2047 			result = "BootstrapResult,Timeout";
2048 		else
2049 			result = "BootstrapResult,Errorsent";
2050 		send_resp(dut, conn, SIGMA_COMPLETE, result);
2051 		goto out;
2052 	}
2053 
2054 	if (frametype && strcasecmp(frametype, "PKEXExchangeResponse") == 0) {
2055 		if (dpp_wait_tx_status(dut, ctrl, 8) < 0)
2056 			result = "BootstrapResult,Timeout";
2057 		else
2058 			result = "BootstrapResult,Errorsent";
2059 		send_resp(dut, conn, SIGMA_COMPLETE, result);
2060 		goto out;
2061 	}
2062 
2063 	if (frametype && strcasecmp(frametype, "PKEXCRRequest") == 0) {
2064 		if (dpp_wait_tx_status(dut, ctrl, 9) < 0)
2065 			result = "BootstrapResult,Timeout";
2066 		else
2067 			result = "BootstrapResult,Errorsent";
2068 		send_resp(dut, conn, SIGMA_COMPLETE, result);
2069 		goto out;
2070 	}
2071 
2072 	if (frametype && strcasecmp(frametype, "PKEXCRResponse") == 0) {
2073 		if (dpp_wait_tx_status(dut, ctrl, 10) < 0)
2074 			result = "BootstrapResult,Timeout";
2075 		else
2076 			result = "BootstrapResult,Errorsent";
2077 		send_resp(dut, conn, SIGMA_COMPLETE, result);
2078 		goto out;
2079 	}
2080 
2081 	if (!frametype && strcasecmp(bs, "PKEX") == 0 &&
2082 	    auth_role && strcasecmp(auth_role, "Responder") == 0) {
2083 		if (dpp_wait_tx_status(dut, ctrl, 10) < 0) {
2084 			send_resp(dut, conn, SIGMA_COMPLETE,
2085 				  "BootstrapResult,Timeout");
2086 			goto out;
2087 		}
2088 	}
2089 
2090 	if (!frametype && strcasecmp(bs, "PKEX") == 0 &&
2091 	    auth_role && strcasecmp(auth_role, "Initiator") == 0) {
2092 		if (dpp_wait_tx(dut, ctrl, 0) < 0) {
2093 			send_resp(dut, conn, SIGMA_COMPLETE,
2094 				  "BootstrapResult,Timeout");
2095 			goto out;
2096 		}
2097 	}
2098 
2099 	if (frametype && strcasecmp(frametype, "AuthenticationRequest") == 0) {
2100 		if (dpp_wait_tx_status(dut, ctrl, 0) < 0) {
2101 			send_resp(dut, conn, SIGMA_COMPLETE,
2102 				  "BootstrapResult,OK,AuthResult,Timeout");
2103 			goto out;
2104 		}
2105 
2106 		if (dpp_wait_rx(dut, ctrl, 1, 5) < 0)
2107 			result = "BootstrapResult,OK,AuthResult,Errorsent,LastFrameReceived,None";
2108 		else if	(get_wpa_cli_events(dut, ctrl, auth_events,
2109 					    buf, sizeof(buf)) >= 0 &&
2110 			 strstr(buf, "DPP-RESPONSE-PENDING") != NULL)
2111 			result = "BootstrapResult,OK,AuthResult,Errorsent,LastFrameReceived,AuthenticationResponseWithStatusPending";
2112 		else
2113 			result = "BootstrapResult,OK,AuthResult,Errorsent,LastFrameReceived,AuthenticationResponse";
2114 		send_resp(dut, conn, SIGMA_COMPLETE, result);
2115 		goto out;
2116 	}
2117 
2118 	if (frametype && strcasecmp(frametype, "AuthenticationResponse") == 0) {
2119 		if (dpp_wait_tx_status(dut, ctrl, 1) < 0) {
2120 			send_resp(dut, conn, SIGMA_COMPLETE,
2121 				  "BootstrapResult,OK,AuthResult,Timeout");
2122 			goto out;
2123 		}
2124 
2125 		if (dpp_wait_rx(dut, ctrl, 2, 5) < 0)
2126 			result = "BootstrapResult,OK,AuthResult,Errorsent,LastFrameReceived,AuthenticationRequest";
2127 		else
2128 			result = "BootstrapResult,OK,AuthResult,Errorsent,LastFrameReceived,AuthenticationConfirm";
2129 		send_resp(dut, conn, SIGMA_COMPLETE, result);
2130 		goto out;
2131 	}
2132 
2133 	if (dpp_process_auth_response(dut, conn, ctrl, auth_events, action_type,
2134 				      check_mutual, buf, sizeof(buf)) < 0)
2135 		goto out;
2136 
2137 	if (frametype && strcasecmp(frametype, "AuthenticationConfirm") == 0) {
2138 		if (dpp_wait_tx_status(dut, ctrl, 2) < 0) {
2139 			send_resp(dut, conn, SIGMA_COMPLETE,
2140 				  "BootstrapResult,OK,AuthResult,Timeout");
2141 			goto out;
2142 		}
2143 
2144 		if (dpp_wait_rx_conf_req(dut, ctrl, 5) < 0)
2145 			result = "BootstrapResult,OK,AuthResult,Errorsent,LastFrameReceived,AuthenticationResponse";
2146 		else
2147 			result = "BootstrapResult,OK,AuthResult,Errorsent,LastFrameReceived,ConfigurationRequest";
2148 		send_resp(dut, conn, SIGMA_COMPLETE, result);
2149 		goto out;
2150 	}
2151 
2152 	if (strstr(buf, "DPP-AUTH-DIRECTION")) {
2153 		res = get_wpa_cli_events(dut, ctrl, auth_events,
2154 					 buf, sizeof(buf));
2155 		if (res < 0) {
2156 			send_resp(dut, conn, SIGMA_COMPLETE,
2157 				  "BootstrapResult,OK,AuthResult,Timeout");
2158 			goto out;
2159 		}
2160 
2161 		sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP auth result: %s", buf);
2162 	}
2163 
2164 	if (strstr(buf, "DPP-NOT-COMPATIBLE")) {
2165 		send_resp(dut, conn, SIGMA_COMPLETE,
2166 			  "BootstrapResult,OK,AuthResult,ROLES_NOT_COMPATIBLE");
2167 		goto out;
2168 	}
2169 
2170 	if (!strstr(buf, "DPP-AUTH-SUCCESS")) {
2171 		send_resp(dut, conn, SIGMA_COMPLETE,
2172 			  "BootstrapResult,OK,AuthResult,FAILED");
2173 		goto out;
2174 	}
2175 
2176 	if (frametype && strcasecmp(frametype, "ConfigurationRequest") == 0) {
2177 		res = get_wpa_cli_event(dut, ctrl, "GAS-QUERY-DONE",
2178 					buf, sizeof(buf));
2179 		if (res < 0)
2180 			result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Timeout";
2181 		else
2182 			result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Errorsent";
2183 		send_resp(dut, conn, SIGMA_COMPLETE, result);
2184 		goto out;
2185 	}
2186 
2187 	if (frametype && strcasecmp(frametype, "ConfigurationResponse") == 0) {
2188 		res = get_wpa_cli_events(dut, ctrl, conf_events,
2189 					 buf, sizeof(buf));
2190 		if (res < 0)
2191 			result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Timeout";
2192 		else
2193 			result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Errorsent,LastFrameReceived,ConfigurationRequest";
2194 		send_resp(dut, conn, SIGMA_COMPLETE, result);
2195 		goto out;
2196 	}
2197 
2198 	res = get_wpa_cli_events(dut, ctrl, conf_events, buf, sizeof(buf));
2199 	if (res < 0) {
2200 		send_resp(dut, conn, SIGMA_COMPLETE,
2201 			  "BootstrapResult,OK,AuthResult,OK,ConfResult,Timeout");
2202 		goto out;
2203 	}
2204 	sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP conf result: %s", buf);
2205 
2206 	if (!strstr(buf, "DPP-CONF-SENT") &&
2207 	    !strstr(buf, "DPP-CONF-RECEIVED")) {
2208 		send_resp(dut, conn, SIGMA_COMPLETE,
2209 			  "BootstrapResult,OK,AuthResult,OK,ConfResult,FAILED");
2210 		goto out;
2211 	}
2212 
2213 	if (conn_status && strstr(buf, "DPP-CONF-SENT") &&
2214 	    strstr(buf, "wait_conn_status=1")) {
2215 		res = get_wpa_cli_event(dut, ctrl, "DPP-CONN-STATUS-RESULT",
2216 					buf, sizeof(buf));
2217 		if (res < 0) {
2218 			send_resp(dut, conn, SIGMA_COMPLETE,
2219 				  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,StatusResult,Timeout");
2220 		} else {
2221 			pos = strstr(buf, "result=");
2222 			if (!pos) {
2223 				send_resp(dut, conn, SIGMA_ERROR,
2224 					  "errorCode,Status result value not reported");
2225 			} else {
2226 				pos += 7;
2227 				snprintf(buf, sizeof(buf),
2228 					 "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,StatusResult,%d",
2229 					 atoi(pos));
2230 				send_resp(dut, conn, SIGMA_COMPLETE, buf);
2231 			}
2232 		}
2233 		goto out;
2234 	}
2235 
2236 	if (strcasecmp(prov_role, "Enrollee") == 0 && netrole &&
2237 	    strcmp(netrole, "configurator") == 0) {
2238 		res = get_wpa_cli_event(dut, ctrl, "DPP-CONFIGURATOR-ID",
2239 					buf, sizeof(buf));
2240 		if (res < 0) {
2241 			send_resp(dut, conn, SIGMA_ERROR,
2242 				  "errorCode,No DPP-CONFIGURATOR-ID");
2243 			goto out;
2244 		}
2245 		pos = strchr(buf, ' ');
2246 		if (!pos) {
2247 			send_resp(dut, conn, SIGMA_ERROR,
2248 				  "errorCode,Invalid DPP-CONFIGURATOR-ID");
2249 			goto out;
2250 		}
2251 		pos++;
2252 		dut->dpp_conf_id = atoi(pos);
2253 	} else if (sigma_dut_is_ap(dut) &&
2254 		   strcasecmp(prov_role, "Enrollee") == 0) {
2255 	update_ap:
2256 		res = dpp_hostapd_conf_update(dut, conn, ifname, ctrl);
2257 		if (res == 0)
2258 			goto out;
2259 		if (res < 0) {
2260 			send_resp(dut, conn, SIGMA_ERROR, NULL);
2261 			goto out;
2262 		}
2263 	}
2264 
2265 	if (strcasecmp(wait_conn, "Yes") == 0 &&
2266 	    !sigma_dut_is_ap(dut) &&
2267 	    strcasecmp(prov_role, "Enrollee") == 0) {
2268 		int netw_id;
2269 		char *pos;
2270 
2271 		res = get_wpa_cli_event(dut, ctrl, "DPP-NETWORK-ID",
2272 					buf, sizeof(buf));
2273 		if (res < 0) {
2274 			send_resp(dut, conn, SIGMA_ERROR,
2275 				  "errorCode,No DPP-NETWORK-ID");
2276 			goto out;
2277 		}
2278 		pos = strchr(buf, ' ');
2279 		if (!pos) {
2280 			send_resp(dut, conn, SIGMA_ERROR,
2281 				  "errorCode,Invalid DPP-NETWORK-ID");
2282 			goto out;
2283 		}
2284 		pos++;
2285 		netw_id = atoi(pos);
2286 		snprintf(buf, sizeof(buf), "GET_NETWORK %d key_mgmt", netw_id);
2287 		if (wpa_command_resp(ifname, buf, buf, sizeof(buf)) < 0) {
2288 			send_resp(dut, conn, SIGMA_ERROR,
2289 				  "errorCode,Could not fetch provisioned key_mgmt");
2290 			goto out;
2291 		}
2292 		if (strncmp(buf, "SAE", 3) == 0) {
2293 			/* SAE generates PMKSA-CACHE-ADDED event */
2294 			not_dpp_akm = 1;
2295 		}
2296 	wait_connect:
2297 		if (frametype && strcasecmp(frametype,
2298 					    "PeerDiscoveryRequest") == 0) {
2299 			if (dpp_wait_tx_status(dut, ctrl, 5) < 0)
2300 				result = "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Timeout";
2301 			else
2302 				result = "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Errorsent";
2303 			send_resp(dut, conn, SIGMA_COMPLETE, result);
2304 			goto out;
2305 		}
2306 
2307 		res = get_wpa_cli_events(dut, ctrl, conn_events,
2308 					 buf, sizeof(buf));
2309 		if (res < 0) {
2310 			send_resp(dut, conn, SIGMA_COMPLETE,
2311 				  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Timeout,NetworkConnectResult,Timeout");
2312 			goto out;
2313 		}
2314 		sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP connect result: %s",
2315 				buf);
2316 
2317 		if (strstr(buf, "PMKSA-CACHE-ADDED")) {
2318 			res = get_wpa_cli_events(dut, ctrl, conn_events,
2319 						 buf, sizeof(buf));
2320 			if (res < 0) {
2321 				send_resp(dut, conn, SIGMA_COMPLETE,
2322 					  not_dpp_akm ?
2323 					  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkConnectResult,Timeout" :
2324 					  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,OK,NetworkConnectResult,Timeout");
2325 				goto out;
2326 			}
2327 			sigma_dut_print(dut, DUT_MSG_DEBUG,
2328 					"DPP connect result: %s", buf);
2329 			if (strstr(buf, "CTRL-EVENT-CONNECTED"))
2330 				send_resp(dut, conn, SIGMA_COMPLETE,
2331 					  not_dpp_akm ?
2332 					  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkConnectResult,OK" :
2333 					  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,OK,NetworkConnectResult,OK");
2334 			else
2335 				send_resp(dut, conn, SIGMA_COMPLETE,
2336 					  not_dpp_akm ?
2337 					  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkConnectResult,Timeout" :
2338 					  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,OK,NetworkConnectResult,Timeout");
2339 			goto out;
2340 		}
2341 
2342 		send_resp(dut, conn, SIGMA_COMPLETE,
2343 			  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkConnectResult,OK");
2344 		goto out;
2345 	}
2346 
2347 	if (strcasecmp(wait_conn, "Yes") == 0 &&
2348 	    frametype && strcasecmp(frametype, "PeerDiscoveryResponse") == 0) {
2349 		if (dpp_wait_tx_status(dut, ctrl, 6) < 0)
2350 			result = "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Timeout";
2351 		else
2352 			result = "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Errorsent";
2353 		send_resp(dut, conn, SIGMA_COMPLETE, result);
2354 		goto out;
2355 	}
2356 
2357 	send_resp(dut, conn, SIGMA_COMPLETE,
2358 		  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK");
2359 out:
2360 	wpa_ctrl_detach(ctrl);
2361 	wpa_ctrl_close(ctrl);
2362 	if (tcp && strcasecmp(tcp, "yes") == 0 &&
2363 	    auth_role && strcasecmp(auth_role, "Responder") == 0)
2364 		wpa_command(ifname, "DPP_CONTROLLER_STOP");
2365 	dut->default_timeout = old_timeout;
2366 	return STATUS_SENT;
2367 err:
2368 	send_resp(dut, conn, SIGMA_ERROR, NULL);
2369 	goto out;
2370 }
2371 
2372 
2373 static enum sigma_cmd_result dpp_manual_dpp(struct sigma_dut *dut,
2374 					    struct sigma_conn *conn,
2375 					    struct sigma_cmd *cmd)
2376 {
2377 	const char *auth_role = get_param(cmd, "DPPAuthRole");
2378 	const char *self_conf = get_param(cmd, "DPPSelfConfigure");
2379 	enum sigma_cmd_result res = INVALID_SEND_STATUS;
2380 	int success;
2381 	const char *val;
2382 	unsigned int old_timeout;
2383 	const char *bs = get_param(cmd, "DPPBS");
2384 
2385 	if (!auth_role) {
2386 		send_resp(dut, conn, SIGMA_ERROR,
2387 			  "errorCode,Missing DPPAuthRole");
2388 		return STATUS_SENT_ERROR;
2389 	}
2390 
2391 	if (!self_conf)
2392 		self_conf = "no";
2393 
2394 	old_timeout = dut->default_timeout;
2395 	val = get_param(cmd, "DPPTimeout");
2396 	if (val && atoi(val) > 0) {
2397 		dut->default_timeout = atoi(val);
2398 		sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP timeout: %u",
2399 				dut->default_timeout);
2400 	}
2401 
2402 	if (strcasecmp(bs, "NFC") == 0) {
2403 		res = dpp_automatic_dpp(dut, conn, cmd);
2404 		goto out;
2405 	}
2406 
2407 	res = dpp_get_local_bootstrap(dut, conn, cmd, 0, &success);
2408 	if (res != STATUS_SENT || !success)
2409 		goto out;
2410 
2411 	if (strcasecmp(auth_role, "Responder") == 0) {
2412 		if (dpp_display_own_qrcode(dut) < 0) {
2413 			send_resp(dut, conn, SIGMA_ERROR,
2414 				  "errorCode,Failed to display own QR code");
2415 			res = STATUS_SENT_ERROR;
2416 			goto out;
2417 		}
2418 
2419 		res = dpp_automatic_dpp(dut, conn, cmd);
2420 		goto out;
2421 	}
2422 
2423 	if (strcasecmp(auth_role, "Initiator") == 0) {
2424 		if (strcasecmp(self_conf, "Yes") != 0) {
2425 			if (dpp_scan_peer_qrcode(dut) < 0) {
2426 				send_resp(dut, conn, SIGMA_ERROR,
2427 					  "errorCode,Failed to scan peer QR Code");
2428 				res = STATUS_SENT_ERROR;
2429 				goto out;
2430 			}
2431 		}
2432 
2433 		res = dpp_automatic_dpp(dut, conn, cmd);
2434 		goto out;
2435 	}
2436 
2437 	send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unknown DPPAuthRole");
2438 	res = STATUS_SENT_ERROR;
2439 out:
2440 	dut->default_timeout = old_timeout;
2441 	return res;
2442 }
2443 
2444 
2445 enum sigma_cmd_result dpp_dev_exec_action(struct sigma_dut *dut,
2446 					  struct sigma_conn *conn,
2447 					  struct sigma_cmd *cmd)
2448 {
2449 	const char *type = get_param(cmd, "DPPActionType");
2450 	const char *bs = get_param(cmd, "DPPBS");
2451 
2452 	if (!bs) {
2453 		send_resp(dut, conn, SIGMA_ERROR,
2454 			  "errorCode,Missing DPPBS");
2455 		return STATUS_SENT_ERROR;
2456 	}
2457 
2458 	if (!type) {
2459 		send_resp(dut, conn, SIGMA_ERROR,
2460 			  "errorCode,Missing DPPActionType");
2461 		return STATUS_SENT_ERROR;
2462 	}
2463 
2464 	if (strcasecmp(type, "GetLocalBootstrap") == 0)
2465 		return dpp_get_local_bootstrap(dut, conn, cmd, 1, NULL);
2466 	if (strcasecmp(type, "SetPeerBootstrap") == 0)
2467 		return dpp_set_peer_bootstrap(dut, conn, cmd);
2468 	if (strcasecmp(type, "ManualDPP") == 0)
2469 		return dpp_manual_dpp(dut, conn, cmd);
2470 	if (strcasecmp(type, "AutomaticDPP") == 0)
2471 		return dpp_automatic_dpp(dut, conn, cmd);
2472 
2473 	send_resp(dut, conn, SIGMA_ERROR,
2474 		  "errorCode,Unsupported DPPActionType");
2475 	return STATUS_SENT_ERROR;
2476 }
2477