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