xref: /wlan-dirver/utils/sigma-dut/dpp.c (revision 4161c3f0b7a61dc599b2f5a60e7ada277845854e)
1d86e5828SJouni Malinen /*
2d86e5828SJouni Malinen  * Sigma Control API DUT (station/AP/sniffer)
3d86e5828SJouni Malinen  * Copyright (c) 2017, Qualcomm Atheros, Inc.
4d86e5828SJouni Malinen  * All Rights Reserved.
5d86e5828SJouni Malinen  * Licensed under the Clear BSD license. See README for more details.
6d86e5828SJouni Malinen  */
7d86e5828SJouni Malinen 
8d86e5828SJouni Malinen #include "sigma_dut.h"
9d86e5828SJouni Malinen #include "wpa_ctrl.h"
10d86e5828SJouni Malinen #include "wpa_helpers.h"
11d86e5828SJouni Malinen 
12d86e5828SJouni Malinen 
13d86e5828SJouni Malinen static int sigma_dut_is_ap(struct sigma_dut *dut)
14d86e5828SJouni Malinen {
15d86e5828SJouni Malinen 	return dut->device_type == AP_unknown ||
16d86e5828SJouni Malinen 		dut->device_type == AP_testbed ||
17d86e5828SJouni Malinen 		dut->device_type == AP_dut;
18d86e5828SJouni Malinen }
19d86e5828SJouni Malinen 
20d86e5828SJouni Malinen 
21d86e5828SJouni Malinen static int dpp_hostapd_run(struct sigma_dut *dut)
22d86e5828SJouni Malinen {
23d86e5828SJouni Malinen 	if (dut->hostapd_running)
24d86e5828SJouni Malinen 		return 0;
25d86e5828SJouni Malinen 
26d86e5828SJouni Malinen 	sigma_dut_print(dut, DUT_MSG_INFO,
27d86e5828SJouni Malinen 			"Starting hostapd in unconfigured state for DPP");
28d86e5828SJouni Malinen 	snprintf(dut->ap_ssid, sizeof(dut->ap_ssid), "unconfigured");
29d86e5828SJouni Malinen 	dut->ap_channel = 11;
30d86e5828SJouni Malinen 	dut->ap_is_dual = 0;
31d86e5828SJouni Malinen 	dut->ap_mode = AP_11ng;
32d86e5828SJouni Malinen 	dut->ap_key_mgmt = AP_OPEN;
33d86e5828SJouni Malinen 	dut->ap_cipher = AP_PLAIN;
34d86e5828SJouni Malinen 	return cmd_ap_config_commit(dut, NULL, NULL) == 1 ? 0 : -1;
35d86e5828SJouni Malinen }
36d86e5828SJouni Malinen 
37d86e5828SJouni Malinen 
38d86e5828SJouni Malinen static const char * dpp_get_curve(struct sigma_cmd *cmd, const char *arg)
39d86e5828SJouni Malinen {
40d86e5828SJouni Malinen 	const char *val = get_param(cmd, arg);
41d86e5828SJouni Malinen 
42d86e5828SJouni Malinen 	if (!val)
43d86e5828SJouni Malinen 		val = "P-256";
44d86e5828SJouni Malinen 	else if (strcasecmp(val, "BP-256R1") == 0)
45d86e5828SJouni Malinen 		val = "BP-256";
46d86e5828SJouni Malinen 	else if (strcasecmp(val, "BP-384R1") == 0)
47d86e5828SJouni Malinen 		val = "BP-384";
48d86e5828SJouni Malinen 	else if (strcasecmp(val, "BP-512R1") == 0)
49d86e5828SJouni Malinen 		val = "BP-512";
50d86e5828SJouni Malinen 
51d86e5828SJouni Malinen 	return val;
52d86e5828SJouni Malinen }
53d86e5828SJouni Malinen 
54d86e5828SJouni Malinen 
55d86e5828SJouni Malinen static int dpp_get_local_bootstrap(struct sigma_dut *dut,
56d86e5828SJouni Malinen 				   struct sigma_conn *conn,
57d86e5828SJouni Malinen 				   struct sigma_cmd *cmd)
58d86e5828SJouni Malinen {
59d86e5828SJouni Malinen 	const char *curve = dpp_get_curve(cmd, "DPPCryptoIdentifier");
60d86e5828SJouni Malinen 	const char *bs = get_param(cmd, "DPPBS");
61*4161c3f0SJouni Malinen 	const char *chan_list = get_param(cmd, "DPPChannelList");
62*4161c3f0SJouni Malinen 	char *pos, mac[50], buf[200], resp[1000], hex[2000];
63d86e5828SJouni Malinen 	const char *ifname = get_station_ifname();
64d86e5828SJouni Malinen 
65d86e5828SJouni Malinen 	if (strcasecmp(bs, "QR") != 0) {
66d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
67d86e5828SJouni Malinen 			  "errorCode,Unsupported DPPBS");
68d86e5828SJouni Malinen 		return 0;
69d86e5828SJouni Malinen 	}
70d86e5828SJouni Malinen 
71d86e5828SJouni Malinen 	if (sigma_dut_is_ap(dut)) {
72d86e5828SJouni Malinen 		u8 bssid[ETH_ALEN];
73d86e5828SJouni Malinen 
74d86e5828SJouni Malinen 		if (!dut->hostapd_ifname) {
75d86e5828SJouni Malinen 			sigma_dut_print(dut, DUT_MSG_ERROR,
76d86e5828SJouni Malinen 					"hostapd ifname not specified (-j)");
77d86e5828SJouni Malinen 			return -2;
78d86e5828SJouni Malinen 		}
79d86e5828SJouni Malinen 		ifname = dut->hostapd_ifname;
80d86e5828SJouni Malinen 		if (get_hwaddr(dut->hostapd_ifname, bssid) < 0) {
81d86e5828SJouni Malinen 			sigma_dut_print(dut, DUT_MSG_ERROR,
82d86e5828SJouni Malinen 					"Could not get MAC address for %s",
83d86e5828SJouni Malinen 					dut->hostapd_ifname);
84d86e5828SJouni Malinen 			return -2;
85d86e5828SJouni Malinen 		}
86d86e5828SJouni Malinen 		snprintf(mac, sizeof(mac), "%02x%02x%02x%02x%02x%02x",
87d86e5828SJouni Malinen 			 bssid[0], bssid[1], bssid[2],
88d86e5828SJouni Malinen 			 bssid[3], bssid[4], bssid[5]);
89d86e5828SJouni Malinen 	} else {
90d86e5828SJouni Malinen 		if (get_wpa_status(ifname, "address", mac, sizeof(mac)) < 0)
91d86e5828SJouni Malinen 			return -2;
92d86e5828SJouni Malinen 	}
93d86e5828SJouni Malinen 
94d86e5828SJouni Malinen 	pos = mac;
95d86e5828SJouni Malinen 	while (*pos) {
96d86e5828SJouni Malinen 		if (*pos == ':')
97d86e5828SJouni Malinen 			memmove(pos, pos + 1, strlen(pos));
98d86e5828SJouni Malinen 		else
99d86e5828SJouni Malinen 			pos++;
100d86e5828SJouni Malinen 	}
101d86e5828SJouni Malinen 
102d86e5828SJouni Malinen 	if (sigma_dut_is_ap(dut) && dpp_hostapd_run(dut) < 0) {
103d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
104d86e5828SJouni Malinen 			  "errorCode,Failed to start hostapd");
105d86e5828SJouni Malinen 		return 0;
106d86e5828SJouni Malinen 	}
107d86e5828SJouni Malinen 
108*4161c3f0SJouni Malinen 	if (chan_list &&
109*4161c3f0SJouni Malinen 	    (strcmp(chan_list, "0/0") == 0 || chan_list[0] == '\0')) {
110*4161c3f0SJouni Malinen 		/* No channel list */
111*4161c3f0SJouni Malinen 		snprintf(buf, sizeof(buf),
112*4161c3f0SJouni Malinen 			 "DPP_BOOTSTRAP_GEN type=qrcode curve=%s mac=%s",
113*4161c3f0SJouni Malinen 			 curve, mac);
114*4161c3f0SJouni Malinen 	} else if (chan_list) {
115*4161c3f0SJouni Malinen 		/* Channel list override (CTT case) - space separated tuple(s)
116*4161c3f0SJouni Malinen 		 * of OperatingClass/Channel; convert to wpa_supplicant/hostapd
117*4161c3f0SJouni Malinen 		 * format: comma separated tuples */
118*4161c3f0SJouni Malinen 		strlcpy(resp, chan_list, sizeof(resp));
119*4161c3f0SJouni Malinen 		for (pos = resp; *pos; pos++) {
120*4161c3f0SJouni Malinen 			if (*pos == ' ')
121*4161c3f0SJouni Malinen 				*pos = ',';
122*4161c3f0SJouni Malinen 		}
123*4161c3f0SJouni Malinen 		snprintf(buf, sizeof(buf),
124*4161c3f0SJouni Malinen 			 "DPP_BOOTSTRAP_GEN type=qrcode curve=%s chan=%s mac=%s",
125*4161c3f0SJouni Malinen 			 curve, resp, mac);
126*4161c3f0SJouni Malinen 	} else {
127*4161c3f0SJouni Malinen 		/* Default channel list (normal DUT case) */
128*4161c3f0SJouni Malinen 		snprintf(buf, sizeof(buf),
129*4161c3f0SJouni Malinen 			 "DPP_BOOTSTRAP_GEN type=qrcode curve=%s chan=81/11 mac=%s",
130*4161c3f0SJouni Malinen 			 curve, mac);
131*4161c3f0SJouni Malinen 	}
132*4161c3f0SJouni Malinen 
133d86e5828SJouni Malinen 	if (wpa_command_resp(ifname, buf, resp, sizeof(resp)) < 0)
134d86e5828SJouni Malinen 		return -2;
135d86e5828SJouni Malinen 	if (strncmp(resp, "FAIL", 4) == 0)
136d86e5828SJouni Malinen 		return -2;
137d86e5828SJouni Malinen 	dut->dpp_local_bootstrap = atoi(resp);
138d86e5828SJouni Malinen 	snprintf(buf, sizeof(buf), "DPP_BOOTSTRAP_GET_URI %d",
139d86e5828SJouni Malinen 		 atoi(resp));
140d86e5828SJouni Malinen 	if (wpa_command_resp(ifname, buf, resp, sizeof(resp)) < 0)
141d86e5828SJouni Malinen 		return -2;
142d86e5828SJouni Malinen 	if (strncmp(resp, "FAIL", 4) == 0)
143d86e5828SJouni Malinen 		return -2;
144d86e5828SJouni Malinen 
145d86e5828SJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "URI: %s", resp);
146d86e5828SJouni Malinen 	ascii2hexstr(resp, hex);
147d86e5828SJouni Malinen 	snprintf(resp, sizeof(resp), "BootstrappingData,%s", hex);
148d86e5828SJouni Malinen 	send_resp(dut, conn, SIGMA_COMPLETE, resp);
149d86e5828SJouni Malinen 	return 0;
150d86e5828SJouni Malinen }
151d86e5828SJouni Malinen 
152d86e5828SJouni Malinen 
153d86e5828SJouni Malinen static int dpp_set_peer_bootstrap(struct sigma_dut *dut,
154d86e5828SJouni Malinen 				  struct sigma_conn *conn,
155d86e5828SJouni Malinen 				  struct sigma_cmd *cmd)
156d86e5828SJouni Malinen {
157d86e5828SJouni Malinen 	const char *val = get_param(cmd, "DPPBootstrappingdata");
158d86e5828SJouni Malinen 	char uri[1000], buf[1200];
159d86e5828SJouni Malinen 	int res;
160d86e5828SJouni Malinen 	const char *ifname = get_station_ifname();
161d86e5828SJouni Malinen 
162d86e5828SJouni Malinen 	if (!val) {
163d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
164d86e5828SJouni Malinen 			  "errorCode,Missing DPPBootstrappingdata");
165d86e5828SJouni Malinen 		return 0;
166d86e5828SJouni Malinen 	}
167d86e5828SJouni Malinen 
168d86e5828SJouni Malinen 	res = parse_hexstr(val, (unsigned char *) uri, sizeof(uri));
169d86e5828SJouni Malinen 	if (res < 0 || (size_t) res >= sizeof(uri))
170d86e5828SJouni Malinen 		return -2;
171d86e5828SJouni Malinen 	uri[res] = '\0';
172d86e5828SJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "URI: %s", uri);
173d86e5828SJouni Malinen 
174d86e5828SJouni Malinen 	snprintf(buf, sizeof(buf), "DPP_QR_CODE %s", uri);
175d86e5828SJouni Malinen 
176d86e5828SJouni Malinen 	if (sigma_dut_is_ap(dut)) {
177d86e5828SJouni Malinen 		if (!dut->hostapd_ifname) {
178d86e5828SJouni Malinen 			sigma_dut_print(dut, DUT_MSG_ERROR,
179d86e5828SJouni Malinen 					"hostapd ifname not specified (-j)");
180d86e5828SJouni Malinen 			return -2;
181d86e5828SJouni Malinen 		}
182d86e5828SJouni Malinen 		ifname = dut->hostapd_ifname;
183d86e5828SJouni Malinen 
184d86e5828SJouni Malinen 		if (dpp_hostapd_run(dut) < 0) {
185d86e5828SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
186d86e5828SJouni Malinen 				  "errorCode,Failed to start hostapd");
187d86e5828SJouni Malinen 			return 0;
188d86e5828SJouni Malinen 		}
189d86e5828SJouni Malinen 	}
190d86e5828SJouni Malinen 
191d86e5828SJouni Malinen 	if (wpa_command_resp(ifname, buf, buf, sizeof(buf)) < 0) {
192d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
193d86e5828SJouni Malinen 			  "errorCode,Failed to parse URI");
194d86e5828SJouni Malinen 		return 0;
195d86e5828SJouni Malinen 	}
196d86e5828SJouni Malinen 	dut->dpp_peer_bootstrap = atoi(buf);
197d86e5828SJouni Malinen 
198d86e5828SJouni Malinen 	return 1;
199d86e5828SJouni Malinen }
200d86e5828SJouni Malinen 
201d86e5828SJouni Malinen 
202d86e5828SJouni Malinen static int dpp_hostapd_conf_update(struct sigma_dut *dut,
203d86e5828SJouni Malinen 				   struct sigma_conn *conn, const char *ifname,
204d86e5828SJouni Malinen 				   struct wpa_ctrl *ctrl)
205d86e5828SJouni Malinen {
206d86e5828SJouni Malinen 	int res;
207d86e5828SJouni Malinen 	char buf[2000], buf2[2500], *pos, *pos2;
208b4c5e3b8SJouni Malinen 	const char *conf_data_events[] = {
209b4c5e3b8SJouni Malinen 		"DPP-CONNECTOR",
210b4c5e3b8SJouni Malinen 		"DPP-CONFOBJ-PASS",
211b4c5e3b8SJouni Malinen 		"DPP-CONFOBJ-PSK",
212b4c5e3b8SJouni Malinen 		NULL
213b4c5e3b8SJouni Malinen 	};
214d86e5828SJouni Malinen 
215d86e5828SJouni Malinen 	sigma_dut_print(dut, DUT_MSG_INFO,
216d86e5828SJouni Malinen 			"Update hostapd configuration based on DPP Config Object");
217d86e5828SJouni Malinen 
218d86e5828SJouni Malinen 	if (wpa_command(ifname, "SET wpa 2") < 0 ||
219d86e5828SJouni Malinen 	    wpa_command(ifname, "SET wpa_key_mgmt DPP") < 0 ||
2200d34723dSJouni Malinen 	    wpa_command(ifname, "SET ieee80211w 1") < 0 ||
221d86e5828SJouni Malinen 	    wpa_command(ifname, "SET rsn_pairwise CCMP") < 0) {
222d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
223d86e5828SJouni Malinen 			  "errorCode,Failed to update AP security parameters");
224d86e5828SJouni Malinen 		goto out;
225d86e5828SJouni Malinen 	}
226d86e5828SJouni Malinen 
227d86e5828SJouni Malinen 	res = get_wpa_cli_event(dut, ctrl, "DPP-CONFOBJ-SSID",
228d86e5828SJouni Malinen 				buf, sizeof(buf));
229d86e5828SJouni Malinen 	if (res < 0) {
230d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
231d86e5828SJouni Malinen 			  "errorCode,No DPP-CONFOBJ-SSID");
232d86e5828SJouni Malinen 		goto out;
233d86e5828SJouni Malinen 	}
234d86e5828SJouni Malinen 	pos = strchr(buf, ' ');
235d86e5828SJouni Malinen 	if (!pos)
236d86e5828SJouni Malinen 		return -2;
237d86e5828SJouni Malinen 	pos++;
238d86e5828SJouni Malinen 	sigma_dut_print(dut, DUT_MSG_INFO,
239d86e5828SJouni Malinen 			"DPP: Config Object SSID: %s", pos);
240d86e5828SJouni Malinen 	snprintf(buf2, sizeof(buf2), "SET ssid %s", pos);
241d86e5828SJouni Malinen 	if (wpa_command(ifname, buf2) < 0) {
242d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
243d86e5828SJouni Malinen 			  "errorCode,Failed to update AP SSID");
244d86e5828SJouni Malinen 		goto out;
245d86e5828SJouni Malinen 	}
246d86e5828SJouni Malinen 
247b4c5e3b8SJouni Malinen 	res = get_wpa_cli_events(dut, ctrl, conf_data_events, buf, sizeof(buf));
248d86e5828SJouni Malinen 	if (res < 0) {
249d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
250b4c5e3b8SJouni Malinen 			  "errorCode,No DPP-CONNECTOR/DPP-CONFOBJ-PASS/PSK");
251d86e5828SJouni Malinen 		goto out;
252d86e5828SJouni Malinen 	}
253b4c5e3b8SJouni Malinen 
254b4c5e3b8SJouni Malinen 	if (!strstr(buf, "DPP-CONNECTOR")) {
255b4c5e3b8SJouni Malinen 		if (wpa_command(ifname, "SET wpa_key_mgmt WPA-PSK") < 0) {
256b4c5e3b8SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
257b4c5e3b8SJouni Malinen 				  "errorCode,Failed to update AP security parameters");
258b4c5e3b8SJouni Malinen 			goto out;
259b4c5e3b8SJouni Malinen 		}
260b4c5e3b8SJouni Malinen 
261b4c5e3b8SJouni Malinen 		pos = strchr(buf, ' ');
262b4c5e3b8SJouni Malinen 		if (!pos)
263b4c5e3b8SJouni Malinen 			return -2;
264b4c5e3b8SJouni Malinen 		pos++;
265b4c5e3b8SJouni Malinen 		if (strstr(buf, "DPP-CONFOBJ-PASS")) {
266b4c5e3b8SJouni Malinen 			char pass[64];
267b4c5e3b8SJouni Malinen 			int pass_len;
268b4c5e3b8SJouni Malinen 
269b4c5e3b8SJouni Malinen 			pass_len = parse_hexstr(pos, (u8 *) pass, sizeof(pass));
270b4c5e3b8SJouni Malinen 			if (pass_len < 0 || pass_len >= sizeof(pass))
271b4c5e3b8SJouni Malinen 				return -2;
272b4c5e3b8SJouni Malinen 			pass[pass_len] = '\0';
273b4c5e3b8SJouni Malinen 			sigma_dut_print(dut, DUT_MSG_INFO,
274b4c5e3b8SJouni Malinen 					"DPP: Passphrase: %s", pass);
275b4c5e3b8SJouni Malinen 			snprintf(buf2, sizeof(buf2), "SET wpa_passphrase %s",
276b4c5e3b8SJouni Malinen 				 pass);
277b4c5e3b8SJouni Malinen 			if (wpa_command(ifname, buf2) < 0) {
278b4c5e3b8SJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
279b4c5e3b8SJouni Malinen 					  "errorCode,Failed to set passphrase");
280b4c5e3b8SJouni Malinen 				goto out;
281b4c5e3b8SJouni Malinen 			}
282b4c5e3b8SJouni Malinen 		} else if (strstr(buf, "DPP-CONFOBJ-PSK")) {
283b4c5e3b8SJouni Malinen 			sigma_dut_print(dut, DUT_MSG_INFO,
284b4c5e3b8SJouni Malinen 					"DPP: PSK: %s", pos);
285b4c5e3b8SJouni Malinen 			snprintf(buf2, sizeof(buf2), "SET wpa_psk %s", pos);
286b4c5e3b8SJouni Malinen 			if (wpa_command(ifname, buf2) < 0) {
287b4c5e3b8SJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
288b4c5e3b8SJouni Malinen 					  "errorCode,Failed to set PSK");
289b4c5e3b8SJouni Malinen 				goto out;
290b4c5e3b8SJouni Malinen 			}
291b4c5e3b8SJouni Malinen 		}
292b4c5e3b8SJouni Malinen 
293b4c5e3b8SJouni Malinen 		goto skip_dpp_akm;
294b4c5e3b8SJouni Malinen 	}
295b4c5e3b8SJouni Malinen 
296d86e5828SJouni Malinen 	pos = strchr(buf, ' ');
297d86e5828SJouni Malinen 	if (!pos)
298d86e5828SJouni Malinen 		return -2;
299d86e5828SJouni Malinen 	pos++;
300d86e5828SJouni Malinen 	sigma_dut_print(dut, DUT_MSG_INFO, "DPP: Connector: %s", pos);
301d86e5828SJouni Malinen 	snprintf(buf2, sizeof(buf2), "SET dpp_connector %s", pos);
302d86e5828SJouni Malinen 	if (wpa_command(ifname, buf2) < 0) {
303d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
304d86e5828SJouni Malinen 			  "errorCode,Failed to update AP Connector");
305d86e5828SJouni Malinen 		goto out;
306d86e5828SJouni Malinen 	}
307d86e5828SJouni Malinen 
308d86e5828SJouni Malinen 	res = get_wpa_cli_event(dut, ctrl, "DPP-C-SIGN-KEY",
309d86e5828SJouni Malinen 				buf, sizeof(buf));
310d86e5828SJouni Malinen 	if (res < 0) {
311d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
312d86e5828SJouni Malinen 			  "errorCode,No DPP-C-SIGN-KEY");
313d86e5828SJouni Malinen 		goto out;
314d86e5828SJouni Malinen 	}
315d86e5828SJouni Malinen 	pos = strchr(buf, ' ');
316d86e5828SJouni Malinen 	if (!pos)
317d86e5828SJouni Malinen 		return -2;
318d86e5828SJouni Malinen 	pos++;
319d86e5828SJouni Malinen 	sigma_dut_print(dut, DUT_MSG_INFO, "DPP: C-sign-key: %s", pos);
320d86e5828SJouni Malinen 	snprintf(buf2, sizeof(buf2), "SET dpp_csign %s", pos);
321d86e5828SJouni Malinen 	if (wpa_command(ifname, buf2) < 0) {
322d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
323d86e5828SJouni Malinen 			  "errorCode,Failed to update AP C-sign-key");
324d86e5828SJouni Malinen 		goto out;
325d86e5828SJouni Malinen 	}
326d86e5828SJouni Malinen 
327d86e5828SJouni Malinen 	res = get_wpa_cli_event(dut, ctrl, "DPP-NET-ACCESS-KEY",
328d86e5828SJouni Malinen 				buf, sizeof(buf));
329d86e5828SJouni Malinen 	if (res < 0) {
330d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
331d86e5828SJouni Malinen 			  "errorCode,No DPP-NET-ACCESS-KEY");
332d86e5828SJouni Malinen 		goto out;
333d86e5828SJouni Malinen 	}
334d86e5828SJouni Malinen 	pos = strchr(buf, ' ');
335d86e5828SJouni Malinen 	if (!pos)
336d86e5828SJouni Malinen 		return -2;
337d86e5828SJouni Malinen 	pos++;
338d86e5828SJouni Malinen 	pos2 = strchr(pos, ' ');
339d86e5828SJouni Malinen 	if (pos2)
340d86e5828SJouni Malinen 		*pos2++ = '\0';
341d86e5828SJouni Malinen 	sigma_dut_print(dut, DUT_MSG_INFO, "DPP: netAccessKey: %s", pos);
342d86e5828SJouni Malinen 	snprintf(buf2, sizeof(buf2), "SET dpp_netaccesskey %s", pos);
343d86e5828SJouni Malinen 	if (wpa_command(ifname, buf2) < 0) {
344d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
345d86e5828SJouni Malinen 			  "errorCode,Failed to update AP netAccessKey");
346d86e5828SJouni Malinen 		goto out;
347d86e5828SJouni Malinen 	}
348d86e5828SJouni Malinen 	if (pos2) {
349d86e5828SJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO,
350d86e5828SJouni Malinen 				"DPP: netAccessKey expiry: %s", pos2);
351d86e5828SJouni Malinen 		snprintf(buf2, sizeof(buf2), "SET dpp_netaccesskey_expiry %s",
352d86e5828SJouni Malinen 			 pos2);
353d86e5828SJouni Malinen 		if (wpa_command(ifname, buf2) < 0) {
354d86e5828SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
355d86e5828SJouni Malinen 				  "errorCode,Failed to update AP netAccessKey expiry");
356d86e5828SJouni Malinen 			goto out;
357d86e5828SJouni Malinen 		}
358d86e5828SJouni Malinen 	}
359b4c5e3b8SJouni Malinen skip_dpp_akm:
360d86e5828SJouni Malinen 
361d86e5828SJouni Malinen 	if (wpa_command(ifname, "DISABLE") < 0 ||
362d86e5828SJouni Malinen 	    wpa_command(ifname, "ENABLE") < 0) {
363d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
364d86e5828SJouni Malinen 			  "errorCode,Failed to update AP configuration");
365d86e5828SJouni Malinen 		goto out;
366d86e5828SJouni Malinen 	}
367d86e5828SJouni Malinen 
368d86e5828SJouni Malinen 	res = get_wpa_cli_event(dut, ctrl, "AP-ENABLED", buf, sizeof(buf));
369d86e5828SJouni Malinen 	if (res < 0) {
370d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,No AP-ENABLED");
371d86e5828SJouni Malinen 		goto out;
372d86e5828SJouni Malinen 	}
373d86e5828SJouni Malinen 
374d86e5828SJouni Malinen 	return 1;
375d86e5828SJouni Malinen out:
376d86e5828SJouni Malinen 	return 0;
377d86e5828SJouni Malinen }
378d86e5828SJouni Malinen 
379d86e5828SJouni Malinen 
380772299f1SJouni Malinen struct dpp_test_info {
381772299f1SJouni Malinen 	const char *step;
382772299f1SJouni Malinen 	const char *frame;
383772299f1SJouni Malinen 	const char *attr;
384772299f1SJouni Malinen 	int value;
385772299f1SJouni Malinen };
386772299f1SJouni Malinen 
387772299f1SJouni Malinen static const struct dpp_test_info dpp_tests[] = {
388772299f1SJouni Malinen 	{ "InvalidValue", "AuthenticationRequest", "WrappedData", 1 },
389772299f1SJouni Malinen 	{ "InvalidValue", "AuthenticationResponse", "WrappedData", 2 },
390772299f1SJouni Malinen 	{ "InvalidValue", "AuthenticationConfirm", "WrappedData", 3 },
391772299f1SJouni Malinen 	{ "InvalidValue", "PKEXCRRequest", "WrappedData", 4 },
392772299f1SJouni Malinen 	{ "InvalidValue", "PKEXCRResponse", "WrappedData", 5 },
393772299f1SJouni Malinen 	{ "InvalidValue", "ConfigurationRequest", "WrappedData", 6 },
394772299f1SJouni Malinen 	{ "InvalidValue", "ConfigurationResponse", "WrappedData", 7 },
395772299f1SJouni Malinen 	{ "InvalidValue", "AuthenticationRequest", "InitCapabilities", 8 },
396772299f1SJouni Malinen 	{ "InvalidValue", "AuthenticationResponse", "RespCapabilities", 9 },
397772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationRequest", "RespBSKeyHash", 10 },
398772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationRequest", "InitBSKeyHash", 11 },
399772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationRequest", "InitProtocolKey", 12 },
400772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationRequest", "InitNonce", 13 },
401772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationRequest", "InitCapabilities", 14 },
402772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationRequest", "WrappedData", 15 },
403772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationResponse", "DPPStatus", 16 },
404772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationResponse", "RespBSKeyHash", 17 },
405772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationResponse", "InitBSKeyHash", 18 },
406772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationResponse", "RespProtocolKey", 19 },
407772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationResponse", "RespNonce", 20 },
408772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationResponse", "InitNonce", 21 },
409772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationResponse", "RespCapabilities",
410772299f1SJouni Malinen 	  22 },
411772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationResponse", "RespAuthTag", 23 },
412772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationResponse", "WrappedData", 24 },
413772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationConfirm", "DPPStatus", 25 },
414772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationConfirm", "RespBSKeyHash", 26 },
415772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationConfirm", "InitBSKeyHash", 27 },
416772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationConfirm", "InitAuthTag", 28 },
417772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationConfirm", "WrappedData", 29 },
418772299f1SJouni Malinen 	{ "InvalidValue", "AuthenticationResponse", "InitNonce", 30 },
419772299f1SJouni Malinen 	{ "InvalidValue", "AuthenticationResponse", "RespCapabilities", 31 },
420772299f1SJouni Malinen 	{ "InvalidValue", "AuthenticationResponse", "RespAuthTag", 32 },
421772299f1SJouni Malinen 	{ "InvalidValue", "AuthenticationConfirm", "InitAuthTag", 33 },
422772299f1SJouni Malinen 	{ "MissingAttribute", "PKEXExchangeRequest", "FiniteCyclicGroup", 34 },
423772299f1SJouni Malinen 	{ "MissingAttribute", "PKEXExchangeRequest", "EncryptedKey", 35 },
424772299f1SJouni Malinen 	{ "MissingAttribute", "PKEXExchangeResponse", "DPPStatus", 36 },
425772299f1SJouni Malinen 	{ "MissingAttribute", "PKEXExchangeResponse", "EncryptedKey", 37 },
426772299f1SJouni Malinen 	{ "MissingAttribute", "PKEXCRRequest", "BSKey", 38 },
427772299f1SJouni Malinen 	{ "MissingAttribute", "PKEXCRRequest", "InitAuthTag", 39 },
428772299f1SJouni Malinen 	{ "MissingAttribute", "PKEXCRRequest", "WrappedData", 40 },
429772299f1SJouni Malinen 	{ "MissingAttribute", "PKEXCRResponse", "BSKey", 41 },
430772299f1SJouni Malinen 	{ "MissingAttribute", "PKEXCRResponse", "RespAuthTag", 42 },
431772299f1SJouni Malinen 	{ "MissingAttribute", "PKEXCRResponse", "WrappedData", 43 },
432772299f1SJouni Malinen 	{ "InvalidValue", "PKEXExchangeRequest", "EncryptedKey", 44 },
433772299f1SJouni Malinen 	{ "InvalidValue", "PKEXExchangeResponse", "EncryptedKey", 45 },
434772299f1SJouni Malinen 	{ "InvalidValue", "PKEXExchangeResponse", "DPPStatus", 46 },
435772299f1SJouni Malinen 	{ "InvalidValue", "PKEXCRRequest", "BSKey", 47 },
436772299f1SJouni Malinen 	{ "InvalidValue", "PKEXCRResponse", "BSKey", 48 },
437772299f1SJouni Malinen 	{ "InvalidValue", "PKEXCRRequest", "InitAuthTag", 49 },
438772299f1SJouni Malinen 	{ "InvalidValue", "PKEXCRResponse", "RespAuthTag", 50 },
439772299f1SJouni Malinen 	{ "MissingAttribute", "ConfigurationRequest", "EnrolleeNonce", 51 },
440772299f1SJouni Malinen 	{ "MissingAttribute", "ConfigurationRequest", "ConfigAttr", 52 },
441772299f1SJouni Malinen 	{ "MissingAttribute", "ConfigurationRequest", "WrappedData", 53 },
442772299f1SJouni Malinen 	{ "MissingAttribute", "ConfigurationResponse", "EnrolleeNonce", 54 },
443772299f1SJouni Malinen 	{ "MissingAttribute", "ConfigurationResponse", "ConfigObj", 55 },
444772299f1SJouni Malinen 	{ "MissingAttribute", "ConfigurationResponse", "DPPStatus", 56 },
445772299f1SJouni Malinen 	{ "MissingAttribute", "ConfigurationResponse", "WrappedData", 57 },
446772299f1SJouni Malinen 	{ "InvalidValue", "ConfigurationResponse", "DPPStatus", 58 },
447772299f1SJouni Malinen 	{ "InvalidValue", "ConfigurationResponse", "EnrolleeNonce", 59 },
44853558e0fSJouni Malinen 	{ "MissingAttribute", "PeerDiscoveryRequest", "TransactionID", 60 },
44953558e0fSJouni Malinen 	{ "MissingAttribute", "PeerDiscoveryRequest", "Connector", 61 },
45053558e0fSJouni Malinen 	{ "MissingAttribute", "PeerDiscoveryResponse", "TransactionID", 62 },
45153558e0fSJouni Malinen 	{ "MissingAttribute", "PeerDiscoveryResponse", "DPPStatus", 63 },
45253558e0fSJouni Malinen 	{ "MissingAttribute", "PeerDiscoveryResponse", "Connector", 64 },
453772299f1SJouni Malinen 	{ NULL, NULL, NULL, 0 }
454772299f1SJouni Malinen };
455772299f1SJouni Malinen 
456772299f1SJouni Malinen 
457772299f1SJouni Malinen static int dpp_get_test(const char *step, const char *frame, const char *attr)
458772299f1SJouni Malinen {
459772299f1SJouni Malinen 	int i;
460772299f1SJouni Malinen 
461772299f1SJouni Malinen 	for (i = 0; dpp_tests[i].step; i++) {
462772299f1SJouni Malinen 		if (strcasecmp(step, dpp_tests[i].step) == 0 &&
463772299f1SJouni Malinen 		    strcasecmp(frame, dpp_tests[i].frame) == 0 &&
464772299f1SJouni Malinen 		    strcasecmp(attr, dpp_tests[i].attr) == 0)
465772299f1SJouni Malinen 			return dpp_tests[i].value;
466772299f1SJouni Malinen 	}
467772299f1SJouni Malinen 
468772299f1SJouni Malinen 	return -1;
469772299f1SJouni Malinen }
470772299f1SJouni Malinen 
471772299f1SJouni Malinen 
472772299f1SJouni Malinen static int dpp_wait_tx_status(struct sigma_dut *dut, struct wpa_ctrl *ctrl,
473772299f1SJouni Malinen 			      int frame_type)
474772299f1SJouni Malinen {
475772299f1SJouni Malinen 	char buf[200], tmp[20];
476772299f1SJouni Malinen 	int res;
477772299f1SJouni Malinen 
478772299f1SJouni Malinen 	snprintf(tmp, sizeof(tmp), "type=%d", frame_type);
479772299f1SJouni Malinen 	for (;;) {
480772299f1SJouni Malinen 		res = get_wpa_cli_event(dut, ctrl, "DPP-TX", buf, sizeof(buf));
481772299f1SJouni Malinen 		if (res < 0)
482772299f1SJouni Malinen 			return -1;
483772299f1SJouni Malinen 		if (strstr(buf, tmp) != NULL)
484772299f1SJouni Malinen 			break;
485772299f1SJouni Malinen 	}
486772299f1SJouni Malinen 
487772299f1SJouni Malinen 	res = get_wpa_cli_event(dut, ctrl, "DPP-TX-STATUS",
488772299f1SJouni Malinen 				buf, sizeof(buf));
489772299f1SJouni Malinen 	if (res < 0 || strstr(buf, "result=FAILED") != NULL)
490772299f1SJouni Malinen 		return -1;
491772299f1SJouni Malinen 
492772299f1SJouni Malinen 	return 0;
493772299f1SJouni Malinen }
494772299f1SJouni Malinen 
495772299f1SJouni Malinen 
496d86e5828SJouni Malinen static int dpp_manual_dpp(struct sigma_dut *dut,
497d86e5828SJouni Malinen 			  struct sigma_conn *conn,
498d86e5828SJouni Malinen 			  struct sigma_cmd *cmd)
499d86e5828SJouni Malinen {
500d86e5828SJouni Malinen 	/* TODO */
501d86e5828SJouni Malinen 	return -1;
502d86e5828SJouni Malinen }
503d86e5828SJouni Malinen 
504d86e5828SJouni Malinen 
505d86e5828SJouni Malinen static int dpp_automatic_dpp(struct sigma_dut *dut,
506d86e5828SJouni Malinen 			     struct sigma_conn *conn,
507d86e5828SJouni Malinen 			     struct sigma_cmd *cmd)
508d86e5828SJouni Malinen {
509d86e5828SJouni Malinen 	const char *bs = get_param(cmd, "DPPBS");
510d86e5828SJouni Malinen 	const char *auth_role = get_param(cmd, "DPPAuthRole");
511d86e5828SJouni Malinen 	const char *prov_role = get_param(cmd, "DPPProvisioningRole");
512d86e5828SJouni Malinen 	const char *pkex_code = get_param(cmd, "DPPPKEXCode");
513d86e5828SJouni Malinen 	const char *pkex_code_id = get_param(cmd, "DPPPKEXCodeIdentifier");
514d86e5828SJouni Malinen 	const char *wait_conn = get_param(cmd, "DPPWaitForConnect");
515d86e5828SJouni Malinen 	const char *self_conf = get_param(cmd, "DPPSelfConfigure");
516772299f1SJouni Malinen 	const char *step = get_param(cmd, "DPPStep");
517772299f1SJouni Malinen 	const char *frametype = get_param(cmd, "DPPFrameType");
518772299f1SJouni Malinen 	const char *attr = get_param(cmd, "DPPIEAttribute");
519d86e5828SJouni Malinen 	const char *role;
520d86e5828SJouni Malinen 	const char *val;
521d86e5828SJouni Malinen 	const char *conf_role;
522d86e5828SJouni Malinen 	int mutual;
523d86e5828SJouni Malinen 	int conf_index = -1;
524d86e5828SJouni Malinen 	char buf[2000];
525d86e5828SJouni Malinen 	char conf_ssid[100];
526d86e5828SJouni Malinen 	char conf_pass[100];
527d86e5828SJouni Malinen 	char pkex_identifier[200];
528d86e5828SJouni Malinen 	struct wpa_ctrl *ctrl;
529d86e5828SJouni Malinen 	int res;
530d86e5828SJouni Malinen 	unsigned int old_timeout;
531d86e5828SJouni Malinen 	int own_pkex_id = -1;
532d86e5828SJouni Malinen 	const char *ifname = get_station_ifname();
533d86e5828SJouni Malinen 	const char *auth_events[] = {
534d86e5828SJouni Malinen 		"DPP-AUTH-SUCCESS",
535d86e5828SJouni Malinen 		"DPP-NOT-COMPATIBLE",
536d86e5828SJouni Malinen 		"DPP-RESPONSE-PENDING",
537d86e5828SJouni Malinen 		"DPP-SCAN-PEER-QR-CODE",
538d86e5828SJouni Malinen 		NULL
539d86e5828SJouni Malinen 	};
540d86e5828SJouni Malinen 	const char *conf_events[] = {
541d86e5828SJouni Malinen 		"DPP-CONF-RECEIVED",
542d86e5828SJouni Malinen 		"DPP-CONF-SENT",
543d86e5828SJouni Malinen 		"DPP-CONF-FAILED",
544d86e5828SJouni Malinen 		NULL
545d86e5828SJouni Malinen 	};
546d86e5828SJouni Malinen 	const char *conn_events[] = {
547d86e5828SJouni Malinen 		"PMKSA-CACHE-ADDED",
548d86e5828SJouni Malinen 		"CTRL-EVENT-CONNECTED",
549d86e5828SJouni Malinen 		NULL
550d86e5828SJouni Malinen 	};
5513d291f70SJouni Malinen 	const char *groups_override = NULL;
552772299f1SJouni Malinen 	const char *result;
553d86e5828SJouni Malinen 
554d86e5828SJouni Malinen 	if (!wait_conn)
555d86e5828SJouni Malinen 		wait_conn = "no";
556d86e5828SJouni Malinen 	if (!self_conf)
557d86e5828SJouni Malinen 		self_conf = "no";
558d86e5828SJouni Malinen 
559d86e5828SJouni Malinen 	if (!auth_role) {
560d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
561d86e5828SJouni Malinen 			  "errorCode,Missing DPPAuthRole");
562d86e5828SJouni Malinen 		return 0;
563d86e5828SJouni Malinen 	}
564d86e5828SJouni Malinen 
565d86e5828SJouni Malinen 	if (!prov_role) {
566d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
567d86e5828SJouni Malinen 			  "errorCode,Missing DPPProvisioningRole");
568d86e5828SJouni Malinen 		return 0;
569d86e5828SJouni Malinen 	}
570d86e5828SJouni Malinen 
571d86e5828SJouni Malinen 	val = get_param(cmd, "DPPAuthDirection");
572d86e5828SJouni Malinen 	mutual = val && strcasecmp(val, "Mutual") == 0;
573d86e5828SJouni Malinen 
574772299f1SJouni Malinen 	if ((step || frametype || attr) && (!step || !frametype || !attr)) {
575772299f1SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
576772299f1SJouni Malinen 			  "errorCode,Invalid DPPStep,DPPFrameType,DPPIEAttribute combination");
577772299f1SJouni Malinen 		return 0;
578772299f1SJouni Malinen 	}
579772299f1SJouni Malinen 
580d86e5828SJouni Malinen 	if (sigma_dut_is_ap(dut)) {
581d86e5828SJouni Malinen 		if (!dut->hostapd_ifname) {
582d86e5828SJouni Malinen 			sigma_dut_print(dut, DUT_MSG_ERROR,
583d86e5828SJouni Malinen 					"hostapd ifname not specified (-j)");
584d86e5828SJouni Malinen 			return -2;
585d86e5828SJouni Malinen 		}
586d86e5828SJouni Malinen 		ifname = dut->hostapd_ifname;
587d86e5828SJouni Malinen 
588d86e5828SJouni Malinen 		if (dpp_hostapd_run(dut) < 0) {
589d86e5828SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
590d86e5828SJouni Malinen 				  "errorCode,Failed to start hostapd");
591d86e5828SJouni Malinen 			return 0;
592d86e5828SJouni Malinen 		}
593d86e5828SJouni Malinen 	}
594d86e5828SJouni Malinen 
595d86e5828SJouni Malinen 	if (strcasecmp(prov_role, "Configurator") == 0) {
596d86e5828SJouni Malinen 		if (dut->dpp_conf_id < 0) {
597d86e5828SJouni Malinen 			snprintf(buf, sizeof(buf),
598d86e5828SJouni Malinen 				 "DPP_CONFIGURATOR_ADD curve=%s",
599d86e5828SJouni Malinen 				 dpp_get_curve(cmd, "DPPSigningKeyECC"));
600d86e5828SJouni Malinen 			if (wpa_command_resp(ifname, buf,
601d86e5828SJouni Malinen 					     buf, sizeof(buf)) < 0) {
602d86e5828SJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
603d86e5828SJouni Malinen 					  "errorCode,Failed to set up configurator");
604d86e5828SJouni Malinen 				return 0;
605d86e5828SJouni Malinen 			}
606d86e5828SJouni Malinen 			dut->dpp_conf_id = atoi(buf);
607d86e5828SJouni Malinen 		}
608d86e5828SJouni Malinen 		role = "configurator";
609d86e5828SJouni Malinen 	} else if (strcasecmp(prov_role, "Enrollee") == 0) {
610d86e5828SJouni Malinen 		role = "enrollee";
611d86e5828SJouni Malinen 	} else {
612d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
613d86e5828SJouni Malinen 			  "errorCode,Unknown DPPProvisioningRole");
614d86e5828SJouni Malinen 		return 0;
615d86e5828SJouni Malinen 	}
616d86e5828SJouni Malinen 
617d86e5828SJouni Malinen 	pkex_identifier[0] = '\0';
618d86e5828SJouni Malinen 	if (strcasecmp(bs, "PKEX") == 0) {
6194f47a272SJouni Malinen 		if (sigma_dut_is_ap(dut) && dut->ap_channel != 6) {
6204f47a272SJouni Malinen 			/* For now, have to make operating channel match DPP
6214f47a272SJouni Malinen 			 * listen channel. This should be removed once hostapd
6224f47a272SJouni Malinen 			 * has support for DPP listen on non-operating channel.
6234f47a272SJouni Malinen 			 */
6244f47a272SJouni Malinen 			sigma_dut_print(dut, DUT_MSG_INFO,
6254f47a272SJouni Malinen 					"Update hostapd operating channel to match listen needs");
6264f47a272SJouni Malinen 			dut->ap_channel = 6;
6274f47a272SJouni Malinen 			if (wpa_command(ifname, "SET channel 6") < 0 ||
6284f47a272SJouni Malinen 			    wpa_command(ifname, "DISABLE") < 0 ||
6294f47a272SJouni Malinen 			    wpa_command(ifname, "ENABLE") < 0) {
6304f47a272SJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
6314f47a272SJouni Malinen 					  "errorCode,Failed to update channel");
6324f47a272SJouni Malinen 				return 0;
6334f47a272SJouni Malinen 			}
6344f47a272SJouni Malinen 		}
6354f47a272SJouni Malinen 
636d86e5828SJouni Malinen 		if (!pkex_code) {
637d86e5828SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
638d86e5828SJouni Malinen 				  "errorCode,Missing DPPPKEXCode");
639d86e5828SJouni Malinen 			return 0;
640d86e5828SJouni Malinen 		}
641d86e5828SJouni Malinen 
642d86e5828SJouni Malinen 		if (pkex_code_id)
643d86e5828SJouni Malinen 			snprintf(pkex_identifier, sizeof(pkex_identifier),
644d86e5828SJouni Malinen 				 "identifier=%s ", pkex_code_id);
645d86e5828SJouni Malinen 
646d86e5828SJouni Malinen 		snprintf(buf, sizeof(buf),
647d86e5828SJouni Malinen 			 "DPP_BOOTSTRAP_GEN type=pkex curve=%s",
648d86e5828SJouni Malinen 			 dpp_get_curve(cmd, "DPPCryptoIdentifier"));
649d86e5828SJouni Malinen 		if (wpa_command_resp(ifname, buf, buf, sizeof(buf)) < 0) {
650d86e5828SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
651d86e5828SJouni Malinen 				  "errorCode,Failed to set up PKEX");
652d86e5828SJouni Malinen 			return 0;
653d86e5828SJouni Malinen 		}
654d86e5828SJouni Malinen 		own_pkex_id = atoi(buf);
655d86e5828SJouni Malinen 	}
656d86e5828SJouni Malinen 
657d86e5828SJouni Malinen 	ctrl = open_wpa_mon(ifname);
658d86e5828SJouni Malinen 	if (!ctrl) {
659d86e5828SJouni Malinen 		sigma_dut_print(dut, DUT_MSG_ERROR,
660d86e5828SJouni Malinen 				"Failed to open wpa_supplicant monitor connection");
661d86e5828SJouni Malinen 		return -2;
662d86e5828SJouni Malinen 	}
663d86e5828SJouni Malinen 
664d86e5828SJouni Malinen 	old_timeout = dut->default_timeout;
665d86e5828SJouni Malinen 	val = get_param(cmd, "DPPTimeout");
666d86e5828SJouni Malinen 	if (val && atoi(val) > 0) {
667d86e5828SJouni Malinen 		dut->default_timeout = atoi(val);
668d86e5828SJouni Malinen 		sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP timeout: %u",
669d86e5828SJouni Malinen 				dut->default_timeout);
670d86e5828SJouni Malinen 	}
671d86e5828SJouni Malinen 
672d86e5828SJouni Malinen 	conf_ssid[0] = '\0';
673d86e5828SJouni Malinen 	conf_pass[0] = '\0';
674d86e5828SJouni Malinen 	val = get_param(cmd, "DPPConfIndex");
675d86e5828SJouni Malinen 	if (val)
676d86e5828SJouni Malinen 		conf_index = atoi(val);
677d86e5828SJouni Malinen 	val = get_param(cmd, "DPPConfEnrolleeRole");
678d86e5828SJouni Malinen 	switch (conf_index) {
679258cc26aSJouni Malinen 	case -1:
680258cc26aSJouni Malinen 		conf_role = NULL;
681258cc26aSJouni Malinen 		break;
682d86e5828SJouni Malinen 	case 1:
683d86e5828SJouni Malinen 		ascii2hexstr("DPPNET01", buf);
684d86e5828SJouni Malinen 		snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
6853d291f70SJouni Malinen 		if (val && strcasecmp(val, "AP") == 0) {
686d86e5828SJouni Malinen 			conf_role = "ap-dpp";
6873d291f70SJouni Malinen 			groups_override = "[{\"groupId\":\"DPPGROUP_DPP_INFRA\",\"netRole\":\"ap\"}]";
6883d291f70SJouni Malinen 		} else {
689d86e5828SJouni Malinen 			conf_role = "sta-dpp";
6903d291f70SJouni Malinen 			groups_override = "[{\"groupId\":\"DPPGROUP_DPP_INFRA\",\"netRole\":\"sta\"}]";
6913d291f70SJouni Malinen 		}
692d86e5828SJouni Malinen 		break;
693d86e5828SJouni Malinen 	case 2:
694d86e5828SJouni Malinen 		ascii2hexstr("DPPNET01", buf);
695d86e5828SJouni Malinen 		snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
6968f81cdfaSJouni Malinen 		snprintf(conf_pass, sizeof(conf_pass),
6978f81cdfaSJouni Malinen 			 "psk=10506e102ad1e7f95112f6b127675bb8344dacacea60403f3fa4055aec85b0fc");
698d86e5828SJouni Malinen 		if (val && strcasecmp(val, "AP") == 0)
699d86e5828SJouni Malinen 			conf_role = "ap-psk";
700d86e5828SJouni Malinen 		else
701d86e5828SJouni Malinen 			conf_role = "sta-psk";
702d86e5828SJouni Malinen 		break;
703d86e5828SJouni Malinen 	case 3:
704d86e5828SJouni Malinen 		ascii2hexstr("DPPNET01", buf);
705d86e5828SJouni Malinen 		snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
706d86e5828SJouni Malinen 		ascii2hexstr("ThisIsDppPassphrase", buf);
707d86e5828SJouni Malinen 		snprintf(conf_pass, sizeof(conf_pass), "pass=%s", buf);
708d86e5828SJouni Malinen 		if (val && strcasecmp(val, "AP") == 0)
709d86e5828SJouni Malinen 			conf_role = "ap-psk";
710d86e5828SJouni Malinen 		else
711d86e5828SJouni Malinen 			conf_role = "sta-psk";
712d86e5828SJouni Malinen 		break;
7133d291f70SJouni Malinen 	case 4:
7143d291f70SJouni Malinen 		ascii2hexstr("DPPNET01", buf);
7153d291f70SJouni Malinen 		snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
7163d291f70SJouni Malinen 		if (val && strcasecmp(val, "AP") == 0) {
7173d291f70SJouni Malinen 			conf_role = "ap-dpp";
7183d291f70SJouni Malinen 			groups_override = "[{\"groupId\":\"DPPGROUP_DPP_INFRA2\",\"netRole\":\"ap\"}]";
7193d291f70SJouni Malinen 		} else {
7203d291f70SJouni Malinen 			conf_role = "sta-dpp";
7213d291f70SJouni Malinen 			groups_override = "[{\"groupId\":\"DPPGROUP_DPP_INFRA2\",\"netRole\":\"sta\"}]";
7223d291f70SJouni Malinen 		}
7233d291f70SJouni Malinen 		break;
724f7490768SJouni Malinen 	default:
725f7490768SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
726f7490768SJouni Malinen 			  "errorCode,Unsupported DPPConfIndex");
727f7490768SJouni Malinen 		goto out;
728d86e5828SJouni Malinen 	}
729d86e5828SJouni Malinen 
7303d291f70SJouni Malinen 	if (groups_override) {
7313d291f70SJouni Malinen 		snprintf(buf, sizeof(buf), "SET dpp_groups_override %s",
7323d291f70SJouni Malinen 			 groups_override);
7333d291f70SJouni Malinen 		if (wpa_command(ifname, buf) < 0) {
7343d291f70SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
7353d291f70SJouni Malinen 				  "errorCode,Failed to set cred:groups");
7363d291f70SJouni Malinen 			goto out;
7373d291f70SJouni Malinen 		}
7383d291f70SJouni Malinen 	}
7393d291f70SJouni Malinen 
740772299f1SJouni Malinen 	if (step) {
741772299f1SJouni Malinen 		int test;
742772299f1SJouni Malinen 
743772299f1SJouni Malinen 		test = dpp_get_test(step, frametype, attr);
744772299f1SJouni Malinen 		if (test <= 0) {
745772299f1SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
746772299f1SJouni Malinen 				  "errorCode,Unsupported DPPStep/DPPFrameType/DPPIEAttribute");
747772299f1SJouni Malinen 			goto out;
748772299f1SJouni Malinen 		}
749772299f1SJouni Malinen 
750772299f1SJouni Malinen 		snprintf(buf, sizeof(buf), "SET dpp_test %d", test);
751772299f1SJouni Malinen 		if (wpa_command(ifname, buf) < 0) {
752772299f1SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
753772299f1SJouni Malinen 				  "errorCode,Failed to set dpp_test");
754772299f1SJouni Malinen 			goto out;
755772299f1SJouni Malinen 		}
756772299f1SJouni Malinen 	} else {
757772299f1SJouni Malinen 		wpa_command(ifname, "SET dpp_test 0");
758772299f1SJouni Malinen 	}
759772299f1SJouni Malinen 
760d86e5828SJouni Malinen 	if (strcasecmp(auth_role, "Initiator") == 0) {
761d86e5828SJouni Malinen 		char own_txt[20];
762d86e5828SJouni Malinen 
763d86e5828SJouni Malinen 		if (mutual)
764d86e5828SJouni Malinen 			snprintf(own_txt, sizeof(own_txt), " own=%d",
765d86e5828SJouni Malinen 				 dut->dpp_local_bootstrap);
766d86e5828SJouni Malinen 		else
767d86e5828SJouni Malinen 			own_txt[0] = '\0';
768d86e5828SJouni Malinen 		if (strcasecmp(bs, "QR") == 0 &&
769d86e5828SJouni Malinen 		    strcasecmp(prov_role, "Configurator") == 0) {
770258cc26aSJouni Malinen 			if (!conf_role) {
771258cc26aSJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
772258cc26aSJouni Malinen 					  "errorCode,Missing DPPConfIndex");
773258cc26aSJouni Malinen 				goto out;
774258cc26aSJouni Malinen 			}
775d86e5828SJouni Malinen 			snprintf(buf, sizeof(buf),
776d86e5828SJouni Malinen 				 "DPP_AUTH_INIT peer=%d%s role=%s conf=%s %s %s configurator=%d",
777d86e5828SJouni Malinen 				 dut->dpp_peer_bootstrap, own_txt, role,
778d86e5828SJouni Malinen 				 conf_role, conf_ssid, conf_pass,
779d86e5828SJouni Malinen 				 dut->dpp_conf_id);
780d86e5828SJouni Malinen 		} else if (strcasecmp(bs, "QR") == 0) {
781d86e5828SJouni Malinen 			snprintf(buf, sizeof(buf),
782d86e5828SJouni Malinen 				 "DPP_AUTH_INIT peer=%d%s role=%s",
783d86e5828SJouni Malinen 				 dut->dpp_peer_bootstrap, own_txt, role);
784d86e5828SJouni Malinen 		} else if (strcasecmp(bs, "PKEX") == 0 &&
785d86e5828SJouni Malinen 			   strcasecmp(prov_role, "Configurator") == 0) {
786258cc26aSJouni Malinen 			if (!conf_role) {
787258cc26aSJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
788258cc26aSJouni Malinen 					  "errorCode,Missing DPPConfIndex");
789258cc26aSJouni Malinen 				goto out;
790258cc26aSJouni Malinen 			}
791d86e5828SJouni Malinen 			snprintf(buf, sizeof(buf),
792d86e5828SJouni Malinen 				 "DPP_PKEX_ADD own=%d init=1 role=%s conf=%s %s %s configurator=%d %scode=%s",
793d86e5828SJouni Malinen 				 own_pkex_id, role, conf_role,
794d86e5828SJouni Malinen 				 conf_ssid, conf_pass, dut->dpp_conf_id,
795d86e5828SJouni Malinen 				 pkex_identifier, pkex_code);
796d86e5828SJouni Malinen 		} else if (strcasecmp(bs, "PKEX") == 0) {
797d86e5828SJouni Malinen 			snprintf(buf, sizeof(buf),
798d86e5828SJouni Malinen 				 "DPP_PKEX_ADD own=%d init=1 role=%s %scode=%s",
799d86e5828SJouni Malinen 				 own_pkex_id, role, pkex_identifier, pkex_code);
800d551c6fcSJouni Malinen 		} else {
801d551c6fcSJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
802d551c6fcSJouni Malinen 				  "errorCode,Unsupported DPPBS");
803d551c6fcSJouni Malinen 			goto out;
804d86e5828SJouni Malinen 		}
805d86e5828SJouni Malinen 		if (wpa_command(ifname, buf) < 0) {
806d86e5828SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
807d86e5828SJouni Malinen 				  "errorCode,Failed to initiate DPP authentication");
808d86e5828SJouni Malinen 			goto out;
809d86e5828SJouni Malinen 		}
810d86e5828SJouni Malinen 	} else if (strcasecmp(auth_role, "Responder") == 0) {
811d86e5828SJouni Malinen 		int freq = 2462;
812d86e5828SJouni Malinen 
813d86e5828SJouni Malinen 		if (strcasecmp(prov_role, "Configurator") == 0) {
814258cc26aSJouni Malinen 			if (!conf_role) {
815258cc26aSJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
816258cc26aSJouni Malinen 					  "errorCode,Missing DPPConfIndex");
817258cc26aSJouni Malinen 				goto out;
818258cc26aSJouni Malinen 			}
819d86e5828SJouni Malinen 			snprintf(buf, sizeof(buf),
820d86e5828SJouni Malinen 				 "SET dpp_configurator_params  conf=%s %s %s configurator=%d",
821d86e5828SJouni Malinen 				 conf_role, conf_ssid, conf_pass,
822d86e5828SJouni Malinen 				 dut->dpp_conf_id);
823d86e5828SJouni Malinen 			if (wpa_command(ifname, buf) < 0) {
824d86e5828SJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
825d86e5828SJouni Malinen 					  "errorCode,Failed to set configurator parameters");
826d86e5828SJouni Malinen 				goto out;
827d86e5828SJouni Malinen 			}
828d86e5828SJouni Malinen 		}
829d86e5828SJouni Malinen 		if (strcasecmp(bs, "PKEX") == 0) {
830d86e5828SJouni Malinen 			freq = 2437;
831d86e5828SJouni Malinen 
832d86e5828SJouni Malinen 			snprintf(buf, sizeof(buf),
833d86e5828SJouni Malinen 				 "DPP_PKEX_ADD own=%d role=%s %scode=%s",
834d86e5828SJouni Malinen 				 own_pkex_id, role, pkex_identifier, pkex_code);
835d86e5828SJouni Malinen 			if (wpa_command(ifname, buf) < 0) {
836d86e5828SJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
837d86e5828SJouni Malinen 					  "errorCode,Failed to configure DPP PKEX");
838d86e5828SJouni Malinen 				goto out;
839d86e5828SJouni Malinen 			}
840d86e5828SJouni Malinen 		}
841d86e5828SJouni Malinen 
842fd7359aeSJouni Malinen 		snprintf(buf, sizeof(buf), "DPP_LISTEN %d role=%s%s",
843fd7359aeSJouni Malinen 			 freq, role,
844fd7359aeSJouni Malinen 			 (strcasecmp(bs, "QR") == 0 && mutual) ?
845fd7359aeSJouni Malinen 			 " qr=mutual" : "");
846d86e5828SJouni Malinen 		if (wpa_command(ifname, buf) < 0) {
847d86e5828SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
848d86e5828SJouni Malinen 				  "errorCode,Failed to start DPP listen");
849d86e5828SJouni Malinen 			goto out;
850d86e5828SJouni Malinen 		}
851d86e5828SJouni Malinen 	} else {
852d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
853d86e5828SJouni Malinen 			  "errorCode,Unknown DPPAuthRole");
854d86e5828SJouni Malinen 		goto out;
855d86e5828SJouni Malinen 	}
856d86e5828SJouni Malinen 
857772299f1SJouni Malinen 	if (frametype && strcasecmp(frametype, "PKEXExchangeRequest") == 0) {
858772299f1SJouni Malinen 		if (dpp_wait_tx_status(dut, ctrl, 7) < 0)
859772299f1SJouni Malinen 			result = "BootstrapResult,Timeout";
860772299f1SJouni Malinen 		else
861772299f1SJouni Malinen 			result = "BootstrapResult,Errorsent";
862772299f1SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, result);
863772299f1SJouni Malinen 		goto out;
864772299f1SJouni Malinen 	}
865772299f1SJouni Malinen 
866772299f1SJouni Malinen 	if (frametype && strcasecmp(frametype, "PKEXExchangeResponse") == 0) {
867772299f1SJouni Malinen 		if (dpp_wait_tx_status(dut, ctrl, 8) < 0)
868772299f1SJouni Malinen 			result = "BootstrapResult,Timeout";
869772299f1SJouni Malinen 		else
870772299f1SJouni Malinen 			result = "BootstrapResult,Errorsent";
871772299f1SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, result);
872772299f1SJouni Malinen 		goto out;
873772299f1SJouni Malinen 	}
874772299f1SJouni Malinen 
875772299f1SJouni Malinen 	if (frametype && strcasecmp(frametype, "PKEXCRRequest") == 0) {
876772299f1SJouni Malinen 		if (dpp_wait_tx_status(dut, ctrl, 9) < 0)
877772299f1SJouni Malinen 			result = "BootstrapResult,Timeout";
878772299f1SJouni Malinen 		else
879772299f1SJouni Malinen 			result = "BootstrapResult,Errorsent";
880772299f1SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, result);
881772299f1SJouni Malinen 		goto out;
882772299f1SJouni Malinen 	}
883772299f1SJouni Malinen 
884772299f1SJouni Malinen 	if (frametype && strcasecmp(frametype, "PKEXCRResponse") == 0) {
885772299f1SJouni Malinen 		if (dpp_wait_tx_status(dut, ctrl, 10) < 0)
886772299f1SJouni Malinen 			result = "BootstrapResult,Timeout";
887772299f1SJouni Malinen 		else
888772299f1SJouni Malinen 			result = "BootstrapResult,Errorsent";
889772299f1SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, result);
890772299f1SJouni Malinen 		goto out;
891772299f1SJouni Malinen 	}
892772299f1SJouni Malinen 
893772299f1SJouni Malinen 	if (frametype && strcasecmp(frametype, "AuthenticationRequest") == 0) {
894772299f1SJouni Malinen 		if (dpp_wait_tx_status(dut, ctrl, 0) < 0)
895772299f1SJouni Malinen 			result = "BootstrapResult,OK,AuthResult,Timeout";
896772299f1SJouni Malinen 		else
897772299f1SJouni Malinen 			result = "BootstrapResult,OK,AuthResult,Errorsent";
898772299f1SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, result);
899772299f1SJouni Malinen 		goto out;
900772299f1SJouni Malinen 	}
901772299f1SJouni Malinen 
902772299f1SJouni Malinen 	if (frametype && strcasecmp(frametype, "AuthenticationResponse") == 0) {
903772299f1SJouni Malinen 		if (dpp_wait_tx_status(dut, ctrl, 1) < 0)
904772299f1SJouni Malinen 			result = "BootstrapResult,OK,AuthResult,Timeout";
905772299f1SJouni Malinen 		else
906772299f1SJouni Malinen 			result = "BootstrapResult,OK,AuthResult,Errorsent";
907772299f1SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, result);
908772299f1SJouni Malinen 		goto out;
909772299f1SJouni Malinen 	}
910772299f1SJouni Malinen 
911772299f1SJouni Malinen 	if (frametype && strcasecmp(frametype, "AuthenticationConfirm") == 0) {
912772299f1SJouni Malinen 		if (dpp_wait_tx_status(dut, ctrl, 2) < 0)
913772299f1SJouni Malinen 			result = "BootstrapResult,OK,AuthResult,Timeout";
914772299f1SJouni Malinen 		else
915772299f1SJouni Malinen 			result = "BootstrapResult,OK,AuthResult,Errorsent";
916772299f1SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, result);
917772299f1SJouni Malinen 		goto out;
918772299f1SJouni Malinen 	}
919772299f1SJouni Malinen 
920d86e5828SJouni Malinen 	res = get_wpa_cli_events(dut, ctrl, auth_events, buf, sizeof(buf));
921d86e5828SJouni Malinen 	if (res < 0) {
922d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE,
923d86e5828SJouni Malinen 			  "BootstrapResult,OK,AuthResult,Timeout");
924d86e5828SJouni Malinen 		goto out;
925d86e5828SJouni Malinen 	}
926d86e5828SJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP auth result: %s", buf);
927d86e5828SJouni Malinen 
928d86e5828SJouni Malinen 	if (strstr(buf, "DPP-NOT-COMPATIBLE")) {
929d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE,
930d86e5828SJouni Malinen 			  "BootstrapResult,OK,AuthResult,ROLES_NOT_COMPATIBLE");
931d86e5828SJouni Malinen 		goto out;
932d86e5828SJouni Malinen 	}
933d86e5828SJouni Malinen 
934d86e5828SJouni Malinen 	if (!strstr(buf, "DPP-AUTH-SUCCESS")) {
935d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE,
936d86e5828SJouni Malinen 			  "BootstrapResult,OK,AuthResult,FAILED");
937d86e5828SJouni Malinen 		goto out;
938d86e5828SJouni Malinen 	}
939d86e5828SJouni Malinen 
940772299f1SJouni Malinen 	if (frametype && strcasecmp(frametype, "ConfigurationRequest") == 0) {
941772299f1SJouni Malinen 		res = get_wpa_cli_event(dut, ctrl, "GAS-QUERY-DONE",
942772299f1SJouni Malinen 					buf, sizeof(buf));
943772299f1SJouni Malinen 		if (res < 0)
944772299f1SJouni Malinen 			result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Timeout";
945772299f1SJouni Malinen 		else
946772299f1SJouni Malinen 			result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Errorsent";
947772299f1SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, result);
948772299f1SJouni Malinen 		goto out;
949772299f1SJouni Malinen 	}
950772299f1SJouni Malinen 
951772299f1SJouni Malinen 	if (frametype && strcasecmp(frametype, "ConfigurationResponse") == 0) {
952772299f1SJouni Malinen 		res = get_wpa_cli_event(dut, ctrl, "DPP-CONF-SENT",
953772299f1SJouni Malinen 					buf, sizeof(buf));
954772299f1SJouni Malinen 		if (res < 0)
955772299f1SJouni Malinen 			result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Timeout";
956772299f1SJouni Malinen 		else
957772299f1SJouni Malinen 			result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Errorsent";
958772299f1SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, result);
959772299f1SJouni Malinen 		goto out;
960772299f1SJouni Malinen 	}
961772299f1SJouni Malinen 
962d86e5828SJouni Malinen 	res = get_wpa_cli_events(dut, ctrl, conf_events, buf, sizeof(buf));
963d86e5828SJouni Malinen 	if (res < 0) {
964d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE,
965d86e5828SJouni Malinen 			  "BootstrapResult,OK,AuthResult,OK,ConfResult,Timeout");
966d86e5828SJouni Malinen 		goto out;
967d86e5828SJouni Malinen 	}
968d86e5828SJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP conf result: %s", buf);
969d86e5828SJouni Malinen 
970d86e5828SJouni Malinen 	if (!strstr(buf, "DPP-CONF-SENT") &&
971d86e5828SJouni Malinen 	    !strstr(buf, "DPP-CONF-RECEIVED")) {
972d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE,
973d86e5828SJouni Malinen 			  "BootstrapResult,OK,AuthResult,OK,ConfResult,FAILED");
974d86e5828SJouni Malinen 		goto out;
975d86e5828SJouni Malinen 	}
976d86e5828SJouni Malinen 
977d86e5828SJouni Malinen 	if (sigma_dut_is_ap(dut) &&
978d86e5828SJouni Malinen 	    strcasecmp(prov_role, "Enrollee") == 0) {
979d86e5828SJouni Malinen 		res = dpp_hostapd_conf_update(dut, conn, ifname, ctrl);
980d86e5828SJouni Malinen 		if (res == 0)
981d86e5828SJouni Malinen 			goto out;
982d86e5828SJouni Malinen 		if (res < 0) {
983d86e5828SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR, NULL);
984d86e5828SJouni Malinen 			goto out;
985d86e5828SJouni Malinen 		}
986d86e5828SJouni Malinen 	}
987d86e5828SJouni Malinen 
988d86e5828SJouni Malinen 	if (strcasecmp(wait_conn, "Yes") == 0 &&
989d86e5828SJouni Malinen 	    !sigma_dut_is_ap(dut) &&
990d86e5828SJouni Malinen 	    strcasecmp(prov_role, "Enrollee") == 0) {
99153558e0fSJouni Malinen 		if (frametype && strcasecmp(frametype,
99253558e0fSJouni Malinen 					    "PeerDiscoveryRequest") == 0) {
99353558e0fSJouni Malinen 			if (dpp_wait_tx_status(dut, ctrl, 5) < 0)
99453558e0fSJouni Malinen 				result = "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Timeout";
99553558e0fSJouni Malinen 			else
99653558e0fSJouni Malinen 				result = "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Errorsent";
99753558e0fSJouni Malinen 			send_resp(dut, conn, SIGMA_COMPLETE, result);
99853558e0fSJouni Malinen 			goto out;
99953558e0fSJouni Malinen 		}
100053558e0fSJouni Malinen 
1001d86e5828SJouni Malinen 		res = get_wpa_cli_events(dut, ctrl, conn_events,
1002d86e5828SJouni Malinen 					 buf, sizeof(buf));
1003d86e5828SJouni Malinen 		if (res < 0) {
1004d86e5828SJouni Malinen 			send_resp(dut, conn, SIGMA_COMPLETE,
1005d86e5828SJouni Malinen 				  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Timeout,NetworkConnectResult,Timeout");
1006d86e5828SJouni Malinen 			goto out;
1007d86e5828SJouni Malinen 		}
1008d86e5828SJouni Malinen 		sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP connect result: %s",
1009d86e5828SJouni Malinen 				buf);
1010d86e5828SJouni Malinen 
1011d86e5828SJouni Malinen 		if (strstr(buf, "PMKSA-CACHE-ADDED")) {
1012d86e5828SJouni Malinen 			res = get_wpa_cli_events(dut, ctrl, conn_events,
1013d86e5828SJouni Malinen 						 buf, sizeof(buf));
1014d86e5828SJouni Malinen 			if (res < 0) {
1015d86e5828SJouni Malinen 				send_resp(dut, conn, SIGMA_COMPLETE,
1016d86e5828SJouni Malinen 					  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,OK,NetworkConnectResult,Timeout");
1017d86e5828SJouni Malinen 				goto out;
1018d86e5828SJouni Malinen 			}
1019d86e5828SJouni Malinen 			sigma_dut_print(dut, DUT_MSG_DEBUG,
1020d86e5828SJouni Malinen 					"DPP connect result: %s", buf);
1021d86e5828SJouni Malinen 			if (strstr(buf, "CTRL-EVENT-CONNECTED"))
1022d86e5828SJouni Malinen 				send_resp(dut, conn, SIGMA_COMPLETE,
1023d86e5828SJouni Malinen 					  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,OK,NetworkConnectResult,OK");
1024d86e5828SJouni Malinen 			else
1025d86e5828SJouni Malinen 				send_resp(dut, conn, SIGMA_COMPLETE,
1026d86e5828SJouni Malinen 					  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,OK,NetworkConnectResult,Timeout");
1027d86e5828SJouni Malinen 			goto out;
1028d86e5828SJouni Malinen 		}
1029d86e5828SJouni Malinen 
1030d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE,
1031d86e5828SJouni Malinen 			  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkConnectResult,OK");
1032d86e5828SJouni Malinen 		goto out;
1033d86e5828SJouni Malinen 	}
1034d86e5828SJouni Malinen 
103553558e0fSJouni Malinen 	if (strcasecmp(wait_conn, "Yes") == 0 &&
103653558e0fSJouni Malinen 	    frametype && strcasecmp(frametype, "PeerDiscoveryResponse") == 0) {
103753558e0fSJouni Malinen 		if (dpp_wait_tx_status(dut, ctrl, 6) < 0)
103853558e0fSJouni Malinen 			result = "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Timeout";
103953558e0fSJouni Malinen 		else
104053558e0fSJouni Malinen 			result = "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Errorsent";
104153558e0fSJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, result);
104253558e0fSJouni Malinen 		goto out;
104353558e0fSJouni Malinen 	}
104453558e0fSJouni Malinen 
1045d86e5828SJouni Malinen 	send_resp(dut, conn, SIGMA_COMPLETE,
1046d86e5828SJouni Malinen 		  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK");
1047d86e5828SJouni Malinen out:
1048d86e5828SJouni Malinen 	wpa_ctrl_detach(ctrl);
1049d86e5828SJouni Malinen 	wpa_ctrl_close(ctrl);
1050d86e5828SJouni Malinen 	dut->default_timeout = old_timeout;
1051d86e5828SJouni Malinen 	return 0;
1052d86e5828SJouni Malinen }
1053d86e5828SJouni Malinen 
1054d86e5828SJouni Malinen 
1055d86e5828SJouni Malinen int dpp_dev_exec_action(struct sigma_dut *dut, struct sigma_conn *conn,
1056d86e5828SJouni Malinen 			struct sigma_cmd *cmd)
1057d86e5828SJouni Malinen {
1058d86e5828SJouni Malinen 	const char *type = get_param(cmd, "DPPActionType");
1059d86e5828SJouni Malinen 	const char *bs = get_param(cmd, "DPPBS");
1060d86e5828SJouni Malinen 
1061d86e5828SJouni Malinen 	if (!bs) {
1062d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
1063d86e5828SJouni Malinen 			  "errorCode,Missing DPPBS");
1064d86e5828SJouni Malinen 		return 0;
1065d86e5828SJouni Malinen 	}
1066d86e5828SJouni Malinen 
1067d86e5828SJouni Malinen 	if (!type) {
1068d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
1069d86e5828SJouni Malinen 			  "errorCode,Missing DPPActionType");
1070d86e5828SJouni Malinen 		return 0;
1071d86e5828SJouni Malinen 	}
1072d86e5828SJouni Malinen 
1073d86e5828SJouni Malinen 	if (strcasecmp(type, "GetLocalBootstrap") == 0)
1074d86e5828SJouni Malinen 		return dpp_get_local_bootstrap(dut, conn, cmd);
1075d86e5828SJouni Malinen 	if (strcasecmp(type, "SetPeerBootstrap") == 0)
1076d86e5828SJouni Malinen 		return dpp_set_peer_bootstrap(dut, conn, cmd);
1077d86e5828SJouni Malinen 	if (strcasecmp(type, "ManualDPP") == 0)
1078d86e5828SJouni Malinen 		return dpp_manual_dpp(dut, conn, cmd);
1079d86e5828SJouni Malinen 	if (strcasecmp(type, "AutomaticDPP") == 0)
1080d86e5828SJouni Malinen 		return dpp_automatic_dpp(dut, conn, cmd);
1081d86e5828SJouni Malinen 
1082d86e5828SJouni Malinen 	send_resp(dut, conn, SIGMA_ERROR,
1083d86e5828SJouni Malinen 		  "errorCode,Unsupported DPPActionType");
1084d86e5828SJouni Malinen 	return 0;
1085d86e5828SJouni Malinen }
1086