xref: /wlan-dirver/utils/sigma-dut/dpp.c (revision 174db64fcfc51fae181edb2e0697a6dad4008abe)
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");
614161c3f0SJouni Malinen 	const char *chan_list = get_param(cmd, "DPPChannelList");
624161c3f0SJouni 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 
1084161c3f0SJouni Malinen 	if (chan_list &&
1094161c3f0SJouni Malinen 	    (strcmp(chan_list, "0/0") == 0 || chan_list[0] == '\0')) {
1104161c3f0SJouni Malinen 		/* No channel list */
1114161c3f0SJouni Malinen 		snprintf(buf, sizeof(buf),
1124161c3f0SJouni Malinen 			 "DPP_BOOTSTRAP_GEN type=qrcode curve=%s mac=%s",
1134161c3f0SJouni Malinen 			 curve, mac);
1144161c3f0SJouni Malinen 	} else if (chan_list) {
1154161c3f0SJouni Malinen 		/* Channel list override (CTT case) - space separated tuple(s)
1164161c3f0SJouni Malinen 		 * of OperatingClass/Channel; convert to wpa_supplicant/hostapd
1174161c3f0SJouni Malinen 		 * format: comma separated tuples */
1184161c3f0SJouni Malinen 		strlcpy(resp, chan_list, sizeof(resp));
1194161c3f0SJouni Malinen 		for (pos = resp; *pos; pos++) {
1204161c3f0SJouni Malinen 			if (*pos == ' ')
1214161c3f0SJouni Malinen 				*pos = ',';
1224161c3f0SJouni Malinen 		}
1234161c3f0SJouni Malinen 		snprintf(buf, sizeof(buf),
1244161c3f0SJouni Malinen 			 "DPP_BOOTSTRAP_GEN type=qrcode curve=%s chan=%s mac=%s",
1254161c3f0SJouni Malinen 			 curve, resp, mac);
1264161c3f0SJouni Malinen 	} else {
1274161c3f0SJouni Malinen 		/* Default channel list (normal DUT case) */
1284161c3f0SJouni Malinen 		snprintf(buf, sizeof(buf),
1294161c3f0SJouni Malinen 			 "DPP_BOOTSTRAP_GEN type=qrcode curve=%s chan=81/11 mac=%s",
1304161c3f0SJouni Malinen 			 curve, mac);
1314161c3f0SJouni Malinen 	}
1324161c3f0SJouni 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");
158b1dd21f8SJouni Malinen 	char uri[1000];
159d86e5828SJouni Malinen 	int res;
160d86e5828SJouni Malinen 
161d86e5828SJouni Malinen 	if (!val) {
162d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
163d86e5828SJouni Malinen 			  "errorCode,Missing DPPBootstrappingdata");
164d86e5828SJouni Malinen 		return 0;
165d86e5828SJouni Malinen 	}
166d86e5828SJouni Malinen 
167d86e5828SJouni Malinen 	res = parse_hexstr(val, (unsigned char *) uri, sizeof(uri));
168d86e5828SJouni Malinen 	if (res < 0 || (size_t) res >= sizeof(uri))
169d86e5828SJouni Malinen 		return -2;
170d86e5828SJouni Malinen 	uri[res] = '\0';
171d86e5828SJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "URI: %s", uri);
172b1dd21f8SJouni Malinen 	free(dut->dpp_peer_uri);
173b1dd21f8SJouni Malinen 	dut->dpp_peer_uri = strdup(uri);
174d86e5828SJouni Malinen 
175d86e5828SJouni Malinen 	return 1;
176d86e5828SJouni Malinen }
177d86e5828SJouni Malinen 
178d86e5828SJouni Malinen 
179d86e5828SJouni Malinen static int dpp_hostapd_conf_update(struct sigma_dut *dut,
180d86e5828SJouni Malinen 				   struct sigma_conn *conn, const char *ifname,
181d86e5828SJouni Malinen 				   struct wpa_ctrl *ctrl)
182d86e5828SJouni Malinen {
183d86e5828SJouni Malinen 	int res;
184d86e5828SJouni Malinen 	char buf[2000], buf2[2500], *pos, *pos2;
185b4c5e3b8SJouni Malinen 	const char *conf_data_events[] = {
186b4c5e3b8SJouni Malinen 		"DPP-CONNECTOR",
187b4c5e3b8SJouni Malinen 		"DPP-CONFOBJ-PASS",
188b4c5e3b8SJouni Malinen 		"DPP-CONFOBJ-PSK",
189b4c5e3b8SJouni Malinen 		NULL
190b4c5e3b8SJouni Malinen 	};
191d86e5828SJouni Malinen 
192d86e5828SJouni Malinen 	sigma_dut_print(dut, DUT_MSG_INFO,
193d86e5828SJouni Malinen 			"Update hostapd configuration based on DPP Config Object");
194d86e5828SJouni Malinen 
195d86e5828SJouni Malinen 	if (wpa_command(ifname, "SET wpa 2") < 0 ||
196d86e5828SJouni Malinen 	    wpa_command(ifname, "SET wpa_key_mgmt DPP") < 0 ||
1970d34723dSJouni Malinen 	    wpa_command(ifname, "SET ieee80211w 1") < 0 ||
198d86e5828SJouni Malinen 	    wpa_command(ifname, "SET rsn_pairwise CCMP") < 0) {
199d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
200d86e5828SJouni Malinen 			  "errorCode,Failed to update AP security parameters");
201d86e5828SJouni Malinen 		goto out;
202d86e5828SJouni Malinen 	}
203d86e5828SJouni Malinen 
204d86e5828SJouni Malinen 	res = get_wpa_cli_event(dut, ctrl, "DPP-CONFOBJ-SSID",
205d86e5828SJouni Malinen 				buf, sizeof(buf));
206d86e5828SJouni Malinen 	if (res < 0) {
207d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
208d86e5828SJouni Malinen 			  "errorCode,No DPP-CONFOBJ-SSID");
209d86e5828SJouni Malinen 		goto out;
210d86e5828SJouni Malinen 	}
211d86e5828SJouni Malinen 	pos = strchr(buf, ' ');
212d86e5828SJouni Malinen 	if (!pos)
213d86e5828SJouni Malinen 		return -2;
214d86e5828SJouni Malinen 	pos++;
215d86e5828SJouni Malinen 	sigma_dut_print(dut, DUT_MSG_INFO,
216d86e5828SJouni Malinen 			"DPP: Config Object SSID: %s", pos);
217d86e5828SJouni Malinen 	snprintf(buf2, sizeof(buf2), "SET ssid %s", pos);
218d86e5828SJouni Malinen 	if (wpa_command(ifname, buf2) < 0) {
219d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
220d86e5828SJouni Malinen 			  "errorCode,Failed to update AP SSID");
221d86e5828SJouni Malinen 		goto out;
222d86e5828SJouni Malinen 	}
223d86e5828SJouni Malinen 
224b4c5e3b8SJouni Malinen 	res = get_wpa_cli_events(dut, ctrl, conf_data_events, buf, sizeof(buf));
225d86e5828SJouni Malinen 	if (res < 0) {
226d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
227b4c5e3b8SJouni Malinen 			  "errorCode,No DPP-CONNECTOR/DPP-CONFOBJ-PASS/PSK");
228d86e5828SJouni Malinen 		goto out;
229d86e5828SJouni Malinen 	}
230b4c5e3b8SJouni Malinen 
231b4c5e3b8SJouni Malinen 	if (!strstr(buf, "DPP-CONNECTOR")) {
232b4c5e3b8SJouni Malinen 		if (wpa_command(ifname, "SET wpa_key_mgmt WPA-PSK") < 0) {
233b4c5e3b8SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
234b4c5e3b8SJouni Malinen 				  "errorCode,Failed to update AP security parameters");
235b4c5e3b8SJouni Malinen 			goto out;
236b4c5e3b8SJouni Malinen 		}
237b4c5e3b8SJouni Malinen 
238b4c5e3b8SJouni Malinen 		pos = strchr(buf, ' ');
239b4c5e3b8SJouni Malinen 		if (!pos)
240b4c5e3b8SJouni Malinen 			return -2;
241b4c5e3b8SJouni Malinen 		pos++;
242b4c5e3b8SJouni Malinen 		if (strstr(buf, "DPP-CONFOBJ-PASS")) {
243b4c5e3b8SJouni Malinen 			char pass[64];
244b4c5e3b8SJouni Malinen 			int pass_len;
245b4c5e3b8SJouni Malinen 
246b4c5e3b8SJouni Malinen 			pass_len = parse_hexstr(pos, (u8 *) pass, sizeof(pass));
247b4c5e3b8SJouni Malinen 			if (pass_len < 0 || pass_len >= sizeof(pass))
248b4c5e3b8SJouni Malinen 				return -2;
249b4c5e3b8SJouni Malinen 			pass[pass_len] = '\0';
250b4c5e3b8SJouni Malinen 			sigma_dut_print(dut, DUT_MSG_INFO,
251b4c5e3b8SJouni Malinen 					"DPP: Passphrase: %s", pass);
252b4c5e3b8SJouni Malinen 			snprintf(buf2, sizeof(buf2), "SET wpa_passphrase %s",
253b4c5e3b8SJouni Malinen 				 pass);
254b4c5e3b8SJouni Malinen 			if (wpa_command(ifname, buf2) < 0) {
255b4c5e3b8SJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
256b4c5e3b8SJouni Malinen 					  "errorCode,Failed to set passphrase");
257b4c5e3b8SJouni Malinen 				goto out;
258b4c5e3b8SJouni Malinen 			}
259b4c5e3b8SJouni Malinen 		} else if (strstr(buf, "DPP-CONFOBJ-PSK")) {
260b4c5e3b8SJouni Malinen 			sigma_dut_print(dut, DUT_MSG_INFO,
261b4c5e3b8SJouni Malinen 					"DPP: PSK: %s", pos);
262b4c5e3b8SJouni Malinen 			snprintf(buf2, sizeof(buf2), "SET wpa_psk %s", pos);
263b4c5e3b8SJouni Malinen 			if (wpa_command(ifname, buf2) < 0) {
264b4c5e3b8SJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
265b4c5e3b8SJouni Malinen 					  "errorCode,Failed to set PSK");
266b4c5e3b8SJouni Malinen 				goto out;
267b4c5e3b8SJouni Malinen 			}
268b4c5e3b8SJouni Malinen 		}
269b4c5e3b8SJouni Malinen 
270b4c5e3b8SJouni Malinen 		goto skip_dpp_akm;
271b4c5e3b8SJouni Malinen 	}
272b4c5e3b8SJouni Malinen 
273d86e5828SJouni Malinen 	pos = strchr(buf, ' ');
274d86e5828SJouni Malinen 	if (!pos)
275d86e5828SJouni Malinen 		return -2;
276d86e5828SJouni Malinen 	pos++;
277d86e5828SJouni Malinen 	sigma_dut_print(dut, DUT_MSG_INFO, "DPP: Connector: %s", pos);
278d86e5828SJouni Malinen 	snprintf(buf2, sizeof(buf2), "SET dpp_connector %s", pos);
279d86e5828SJouni Malinen 	if (wpa_command(ifname, buf2) < 0) {
280d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
281d86e5828SJouni Malinen 			  "errorCode,Failed to update AP Connector");
282d86e5828SJouni Malinen 		goto out;
283d86e5828SJouni Malinen 	}
284d86e5828SJouni Malinen 
285d86e5828SJouni Malinen 	res = get_wpa_cli_event(dut, ctrl, "DPP-C-SIGN-KEY",
286d86e5828SJouni Malinen 				buf, sizeof(buf));
287d86e5828SJouni Malinen 	if (res < 0) {
288d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
289d86e5828SJouni Malinen 			  "errorCode,No DPP-C-SIGN-KEY");
290d86e5828SJouni Malinen 		goto out;
291d86e5828SJouni Malinen 	}
292d86e5828SJouni Malinen 	pos = strchr(buf, ' ');
293d86e5828SJouni Malinen 	if (!pos)
294d86e5828SJouni Malinen 		return -2;
295d86e5828SJouni Malinen 	pos++;
296d86e5828SJouni Malinen 	sigma_dut_print(dut, DUT_MSG_INFO, "DPP: C-sign-key: %s", pos);
297d86e5828SJouni Malinen 	snprintf(buf2, sizeof(buf2), "SET dpp_csign %s", pos);
298d86e5828SJouni Malinen 	if (wpa_command(ifname, buf2) < 0) {
299d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
300d86e5828SJouni Malinen 			  "errorCode,Failed to update AP C-sign-key");
301d86e5828SJouni Malinen 		goto out;
302d86e5828SJouni Malinen 	}
303d86e5828SJouni Malinen 
304d86e5828SJouni Malinen 	res = get_wpa_cli_event(dut, ctrl, "DPP-NET-ACCESS-KEY",
305d86e5828SJouni Malinen 				buf, sizeof(buf));
306d86e5828SJouni Malinen 	if (res < 0) {
307d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
308d86e5828SJouni Malinen 			  "errorCode,No DPP-NET-ACCESS-KEY");
309d86e5828SJouni Malinen 		goto out;
310d86e5828SJouni Malinen 	}
311d86e5828SJouni Malinen 	pos = strchr(buf, ' ');
312d86e5828SJouni Malinen 	if (!pos)
313d86e5828SJouni Malinen 		return -2;
314d86e5828SJouni Malinen 	pos++;
315d86e5828SJouni Malinen 	pos2 = strchr(pos, ' ');
316d86e5828SJouni Malinen 	if (pos2)
317d86e5828SJouni Malinen 		*pos2++ = '\0';
318d86e5828SJouni Malinen 	sigma_dut_print(dut, DUT_MSG_INFO, "DPP: netAccessKey: %s", pos);
319d86e5828SJouni Malinen 	snprintf(buf2, sizeof(buf2), "SET dpp_netaccesskey %s", pos);
320d86e5828SJouni Malinen 	if (wpa_command(ifname, buf2) < 0) {
321d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
322d86e5828SJouni Malinen 			  "errorCode,Failed to update AP netAccessKey");
323d86e5828SJouni Malinen 		goto out;
324d86e5828SJouni Malinen 	}
325d86e5828SJouni Malinen 	if (pos2) {
326d86e5828SJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO,
327d86e5828SJouni Malinen 				"DPP: netAccessKey expiry: %s", pos2);
328d86e5828SJouni Malinen 		snprintf(buf2, sizeof(buf2), "SET dpp_netaccesskey_expiry %s",
329d86e5828SJouni Malinen 			 pos2);
330d86e5828SJouni Malinen 		if (wpa_command(ifname, buf2) < 0) {
331d86e5828SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
332d86e5828SJouni Malinen 				  "errorCode,Failed to update AP netAccessKey expiry");
333d86e5828SJouni Malinen 			goto out;
334d86e5828SJouni Malinen 		}
335d86e5828SJouni Malinen 	}
336b4c5e3b8SJouni Malinen skip_dpp_akm:
337d86e5828SJouni Malinen 
338d86e5828SJouni Malinen 	if (wpa_command(ifname, "DISABLE") < 0 ||
339d86e5828SJouni Malinen 	    wpa_command(ifname, "ENABLE") < 0) {
340d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
341d86e5828SJouni Malinen 			  "errorCode,Failed to update AP configuration");
342d86e5828SJouni Malinen 		goto out;
343d86e5828SJouni Malinen 	}
344d86e5828SJouni Malinen 
345d86e5828SJouni Malinen 	res = get_wpa_cli_event(dut, ctrl, "AP-ENABLED", buf, sizeof(buf));
346d86e5828SJouni Malinen 	if (res < 0) {
347d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,No AP-ENABLED");
348d86e5828SJouni Malinen 		goto out;
349d86e5828SJouni Malinen 	}
350d86e5828SJouni Malinen 
351d86e5828SJouni Malinen 	return 1;
352d86e5828SJouni Malinen out:
353d86e5828SJouni Malinen 	return 0;
354d86e5828SJouni Malinen }
355d86e5828SJouni Malinen 
356d86e5828SJouni Malinen 
357772299f1SJouni Malinen struct dpp_test_info {
358772299f1SJouni Malinen 	const char *step;
359772299f1SJouni Malinen 	const char *frame;
360772299f1SJouni Malinen 	const char *attr;
361772299f1SJouni Malinen 	int value;
362772299f1SJouni Malinen };
363772299f1SJouni Malinen 
364772299f1SJouni Malinen static const struct dpp_test_info dpp_tests[] = {
365772299f1SJouni Malinen 	{ "InvalidValue", "AuthenticationRequest", "WrappedData", 1 },
366772299f1SJouni Malinen 	{ "InvalidValue", "AuthenticationResponse", "WrappedData", 2 },
367f96fcee3SJouni Malinen 	{ "InvalidValue", "AuthenticationResponse", "PrimaryWrappedData", 2 },
368772299f1SJouni Malinen 	{ "InvalidValue", "AuthenticationConfirm", "WrappedData", 3 },
369772299f1SJouni Malinen 	{ "InvalidValue", "PKEXCRRequest", "WrappedData", 4 },
370772299f1SJouni Malinen 	{ "InvalidValue", "PKEXCRResponse", "WrappedData", 5 },
371772299f1SJouni Malinen 	{ "InvalidValue", "ConfigurationRequest", "WrappedData", 6 },
372772299f1SJouni Malinen 	{ "InvalidValue", "ConfigurationResponse", "WrappedData", 7 },
373772299f1SJouni Malinen 	{ "InvalidValue", "AuthenticationRequest", "InitCapabilities", 8 },
374772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationRequest", "RespBSKeyHash", 10 },
375772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationRequest", "InitBSKeyHash", 11 },
376772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationRequest", "InitProtocolKey", 12 },
377772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationRequest", "InitNonce", 13 },
378772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationRequest", "InitCapabilities", 14 },
379772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationRequest", "WrappedData", 15 },
380772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationResponse", "DPPStatus", 16 },
381772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationResponse", "RespBSKeyHash", 17 },
382772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationResponse", "InitBSKeyHash", 18 },
383772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationResponse", "RespProtocolKey", 19 },
384772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationResponse", "RespNonce", 20 },
385772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationResponse", "InitNonce", 21 },
386772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationResponse", "RespCapabilities",
387772299f1SJouni Malinen 	  22 },
388772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationResponse", "RespAuthTag", 23 },
389772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationResponse", "WrappedData", 24 },
390f96fcee3SJouni Malinen 	{ "MissingAttribute", "AuthenticationResponse", "PrimaryWrappedData",
391f96fcee3SJouni Malinen 	  24 },
392772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationConfirm", "DPPStatus", 25 },
393772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationConfirm", "RespBSKeyHash", 26 },
394772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationConfirm", "InitBSKeyHash", 27 },
395772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationConfirm", "InitAuthTag", 28 },
396772299f1SJouni Malinen 	{ "MissingAttribute", "AuthenticationConfirm", "WrappedData", 29 },
397772299f1SJouni Malinen 	{ "InvalidValue", "AuthenticationResponse", "InitNonce", 30 },
398772299f1SJouni Malinen 	{ "InvalidValue", "AuthenticationResponse", "RespCapabilities", 31 },
399772299f1SJouni Malinen 	{ "InvalidValue", "AuthenticationResponse", "RespAuthTag", 32 },
400772299f1SJouni Malinen 	{ "InvalidValue", "AuthenticationConfirm", "InitAuthTag", 33 },
401772299f1SJouni Malinen 	{ "MissingAttribute", "PKEXExchangeRequest", "FiniteCyclicGroup", 34 },
402772299f1SJouni Malinen 	{ "MissingAttribute", "PKEXExchangeRequest", "EncryptedKey", 35 },
403772299f1SJouni Malinen 	{ "MissingAttribute", "PKEXExchangeResponse", "DPPStatus", 36 },
404772299f1SJouni Malinen 	{ "MissingAttribute", "PKEXExchangeResponse", "EncryptedKey", 37 },
405772299f1SJouni Malinen 	{ "MissingAttribute", "PKEXCRRequest", "BSKey", 38 },
406772299f1SJouni Malinen 	{ "MissingAttribute", "PKEXCRRequest", "InitAuthTag", 39 },
407772299f1SJouni Malinen 	{ "MissingAttribute", "PKEXCRRequest", "WrappedData", 40 },
408772299f1SJouni Malinen 	{ "MissingAttribute", "PKEXCRResponse", "BSKey", 41 },
409772299f1SJouni Malinen 	{ "MissingAttribute", "PKEXCRResponse", "RespAuthTag", 42 },
410772299f1SJouni Malinen 	{ "MissingAttribute", "PKEXCRResponse", "WrappedData", 43 },
411772299f1SJouni Malinen 	{ "InvalidValue", "PKEXExchangeRequest", "EncryptedKey", 44 },
412772299f1SJouni Malinen 	{ "InvalidValue", "PKEXExchangeResponse", "EncryptedKey", 45 },
413772299f1SJouni Malinen 	{ "InvalidValue", "PKEXExchangeResponse", "DPPStatus", 46 },
414772299f1SJouni Malinen 	{ "InvalidValue", "PKEXCRRequest", "BSKey", 47 },
415772299f1SJouni Malinen 	{ "InvalidValue", "PKEXCRResponse", "BSKey", 48 },
416772299f1SJouni Malinen 	{ "InvalidValue", "PKEXCRRequest", "InitAuthTag", 49 },
417772299f1SJouni Malinen 	{ "InvalidValue", "PKEXCRResponse", "RespAuthTag", 50 },
418772299f1SJouni Malinen 	{ "MissingAttribute", "ConfigurationRequest", "EnrolleeNonce", 51 },
419772299f1SJouni Malinen 	{ "MissingAttribute", "ConfigurationRequest", "ConfigAttr", 52 },
420772299f1SJouni Malinen 	{ "MissingAttribute", "ConfigurationRequest", "WrappedData", 53 },
421772299f1SJouni Malinen 	{ "MissingAttribute", "ConfigurationResponse", "EnrolleeNonce", 54 },
422772299f1SJouni Malinen 	{ "MissingAttribute", "ConfigurationResponse", "ConfigObj", 55 },
423772299f1SJouni Malinen 	{ "MissingAttribute", "ConfigurationResponse", "DPPStatus", 56 },
424772299f1SJouni Malinen 	{ "MissingAttribute", "ConfigurationResponse", "WrappedData", 57 },
425772299f1SJouni Malinen 	{ "InvalidValue", "ConfigurationResponse", "DPPStatus", 58 },
426772299f1SJouni Malinen 	{ "InvalidValue", "ConfigurationResponse", "EnrolleeNonce", 59 },
42753558e0fSJouni Malinen 	{ "MissingAttribute", "PeerDiscoveryRequest", "TransactionID", 60 },
42853558e0fSJouni Malinen 	{ "MissingAttribute", "PeerDiscoveryRequest", "Connector", 61 },
42953558e0fSJouni Malinen 	{ "MissingAttribute", "PeerDiscoveryResponse", "TransactionID", 62 },
43053558e0fSJouni Malinen 	{ "MissingAttribute", "PeerDiscoveryResponse", "DPPStatus", 63 },
43153558e0fSJouni Malinen 	{ "MissingAttribute", "PeerDiscoveryResponse", "Connector", 64 },
432ae624487SJouni Malinen 	{ "InvalidValue", "AuthenticationRequest", "InitProtocolKey", 66 },
433ae624487SJouni Malinen 	{ "InvalidValue", "AuthenticationResponse", "RespProtocolKey", 67 },
434ae624487SJouni Malinen 	{ "InvalidValue", "AuthenticationRequest", "RespBSKeyHash", 68 },
435ae624487SJouni Malinen 	{ "InvalidValue", "AuthenticationRequest", "InitBSKeyHash", 69 },
436ae624487SJouni Malinen 	{ "InvalidValue", "AuthenticationResponse", "RespBSKeyHash", 70 },
437ae624487SJouni Malinen 	{ "InvalidValue", "AuthenticationResponse", "InitBSKeyHash", 71 },
438ae624487SJouni Malinen 	{ "InvalidValue", "AuthenticationConfirm", "RespBSKeyHash", 72 },
439ae624487SJouni Malinen 	{ "InvalidValue", "AuthenticationConfirm", "InitBSKeyHash", 73 },
440ae624487SJouni Malinen 	{ "InvalidValue", "AuthenticationResponse", "DPPStatus", 74 },
441ae624487SJouni Malinen 	{ "InvalidValue", "AuthenticationConfirm", "DPPStatus", 75 },
442ae624487SJouni Malinen 	{ "InvalidValue", "ConfigurationRequest", "ConfigAttr", 76 },
443ae624487SJouni Malinen 	{ "InvalidValue", "PeerDiscoveryResponse", "TransactionID", 77 },
444ae624487SJouni Malinen 	{ "InvalidValue", "PeerDiscoveryResponse", "DPPStatus", 78 },
445ae624487SJouni Malinen 	{ "InvalidValue", "PeerDiscoveryResponse", "Connector", 79 },
446ae624487SJouni Malinen 	{ "InvalidValue", "PeerDiscoveryRequest", "Connector", 80 },
44767795a76SJouni Malinen 	{ "InvalidValue", "AuthenticationRequest", "InitNonce", 81 },
448772299f1SJouni Malinen 	{ NULL, NULL, NULL, 0 }
449772299f1SJouni Malinen };
450772299f1SJouni Malinen 
451772299f1SJouni Malinen 
452772299f1SJouni Malinen static int dpp_get_test(const char *step, const char *frame, const char *attr)
453772299f1SJouni Malinen {
454772299f1SJouni Malinen 	int i;
455772299f1SJouni Malinen 
456772299f1SJouni Malinen 	for (i = 0; dpp_tests[i].step; i++) {
457772299f1SJouni Malinen 		if (strcasecmp(step, dpp_tests[i].step) == 0 &&
458772299f1SJouni Malinen 		    strcasecmp(frame, dpp_tests[i].frame) == 0 &&
459772299f1SJouni Malinen 		    strcasecmp(attr, dpp_tests[i].attr) == 0)
460772299f1SJouni Malinen 			return dpp_tests[i].value;
461772299f1SJouni Malinen 	}
462772299f1SJouni Malinen 
463772299f1SJouni Malinen 	return -1;
464772299f1SJouni Malinen }
465772299f1SJouni Malinen 
466772299f1SJouni Malinen 
467772299f1SJouni Malinen static int dpp_wait_tx_status(struct sigma_dut *dut, struct wpa_ctrl *ctrl,
468772299f1SJouni Malinen 			      int frame_type)
469772299f1SJouni Malinen {
470772299f1SJouni Malinen 	char buf[200], tmp[20];
471772299f1SJouni Malinen 	int res;
472772299f1SJouni Malinen 
473772299f1SJouni Malinen 	snprintf(tmp, sizeof(tmp), "type=%d", frame_type);
474772299f1SJouni Malinen 	for (;;) {
475772299f1SJouni Malinen 		res = get_wpa_cli_event(dut, ctrl, "DPP-TX", buf, sizeof(buf));
476772299f1SJouni Malinen 		if (res < 0)
477772299f1SJouni Malinen 			return -1;
478772299f1SJouni Malinen 		if (strstr(buf, tmp) != NULL)
479772299f1SJouni Malinen 			break;
480772299f1SJouni Malinen 	}
481772299f1SJouni Malinen 
482772299f1SJouni Malinen 	res = get_wpa_cli_event(dut, ctrl, "DPP-TX-STATUS",
483772299f1SJouni Malinen 				buf, sizeof(buf));
484772299f1SJouni Malinen 	if (res < 0 || strstr(buf, "result=FAILED") != NULL)
485772299f1SJouni Malinen 		return -1;
486772299f1SJouni Malinen 
487772299f1SJouni Malinen 	return 0;
488772299f1SJouni Malinen }
489772299f1SJouni Malinen 
490772299f1SJouni Malinen 
491d86e5828SJouni Malinen static int dpp_manual_dpp(struct sigma_dut *dut,
492d86e5828SJouni Malinen 			  struct sigma_conn *conn,
493d86e5828SJouni Malinen 			  struct sigma_cmd *cmd)
494d86e5828SJouni Malinen {
495d86e5828SJouni Malinen 	/* TODO */
496d86e5828SJouni Malinen 	return -1;
497d86e5828SJouni Malinen }
498d86e5828SJouni Malinen 
499d86e5828SJouni Malinen 
500d86e5828SJouni Malinen static int dpp_automatic_dpp(struct sigma_dut *dut,
501d86e5828SJouni Malinen 			     struct sigma_conn *conn,
502d86e5828SJouni Malinen 			     struct sigma_cmd *cmd)
503d86e5828SJouni Malinen {
504d86e5828SJouni Malinen 	const char *bs = get_param(cmd, "DPPBS");
505d86e5828SJouni Malinen 	const char *auth_role = get_param(cmd, "DPPAuthRole");
506d86e5828SJouni Malinen 	const char *prov_role = get_param(cmd, "DPPProvisioningRole");
507d86e5828SJouni Malinen 	const char *pkex_code = get_param(cmd, "DPPPKEXCode");
508d86e5828SJouni Malinen 	const char *pkex_code_id = get_param(cmd, "DPPPKEXCodeIdentifier");
509d86e5828SJouni Malinen 	const char *wait_conn = get_param(cmd, "DPPWaitForConnect");
510d86e5828SJouni Malinen 	const char *self_conf = get_param(cmd, "DPPSelfConfigure");
511772299f1SJouni Malinen 	const char *step = get_param(cmd, "DPPStep");
512772299f1SJouni Malinen 	const char *frametype = get_param(cmd, "DPPFrameType");
513772299f1SJouni Malinen 	const char *attr = get_param(cmd, "DPPIEAttribute");
514d86e5828SJouni Malinen 	const char *role;
515d86e5828SJouni Malinen 	const char *val;
516d86e5828SJouni Malinen 	const char *conf_role;
517d86e5828SJouni Malinen 	int conf_index = -1;
518d86e5828SJouni Malinen 	char buf[2000];
519d86e5828SJouni Malinen 	char conf_ssid[100];
520d86e5828SJouni Malinen 	char conf_pass[100];
521d86e5828SJouni Malinen 	char pkex_identifier[200];
522d86e5828SJouni Malinen 	struct wpa_ctrl *ctrl;
523d86e5828SJouni Malinen 	int res;
524d86e5828SJouni Malinen 	unsigned int old_timeout;
525d86e5828SJouni Malinen 	int own_pkex_id = -1;
526d86e5828SJouni Malinen 	const char *ifname = get_station_ifname();
527d86e5828SJouni Malinen 	const char *auth_events[] = {
528d86e5828SJouni Malinen 		"DPP-AUTH-SUCCESS",
529d86e5828SJouni Malinen 		"DPP-NOT-COMPATIBLE",
530d86e5828SJouni Malinen 		"DPP-RESPONSE-PENDING",
531d86e5828SJouni Malinen 		"DPP-SCAN-PEER-QR-CODE",
532d86e5828SJouni Malinen 		NULL
533d86e5828SJouni Malinen 	};
534d86e5828SJouni Malinen 	const char *conf_events[] = {
535d86e5828SJouni Malinen 		"DPP-CONF-RECEIVED",
536d86e5828SJouni Malinen 		"DPP-CONF-SENT",
537d86e5828SJouni Malinen 		"DPP-CONF-FAILED",
538d86e5828SJouni Malinen 		NULL
539d86e5828SJouni Malinen 	};
540d86e5828SJouni Malinen 	const char *conn_events[] = {
541d86e5828SJouni Malinen 		"PMKSA-CACHE-ADDED",
542d86e5828SJouni Malinen 		"CTRL-EVENT-CONNECTED",
543d86e5828SJouni Malinen 		NULL
544d86e5828SJouni Malinen 	};
5453d291f70SJouni Malinen 	const char *groups_override = NULL;
546772299f1SJouni Malinen 	const char *result;
547d86e5828SJouni Malinen 
548d86e5828SJouni Malinen 	if (!wait_conn)
549d86e5828SJouni Malinen 		wait_conn = "no";
550d86e5828SJouni Malinen 	if (!self_conf)
551d86e5828SJouni Malinen 		self_conf = "no";
552d86e5828SJouni Malinen 
553d86e5828SJouni Malinen 	if (!auth_role) {
554d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
555d86e5828SJouni Malinen 			  "errorCode,Missing DPPAuthRole");
556d86e5828SJouni Malinen 		return 0;
557d86e5828SJouni Malinen 	}
558d86e5828SJouni Malinen 
559d86e5828SJouni Malinen 	if (!prov_role) {
560d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
561d86e5828SJouni Malinen 			  "errorCode,Missing DPPProvisioningRole");
562d86e5828SJouni Malinen 		return 0;
563d86e5828SJouni Malinen 	}
564d86e5828SJouni Malinen 
565772299f1SJouni Malinen 	if ((step || frametype || attr) && (!step || !frametype || !attr)) {
566772299f1SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
567772299f1SJouni Malinen 			  "errorCode,Invalid DPPStep,DPPFrameType,DPPIEAttribute combination");
568772299f1SJouni Malinen 		return 0;
569772299f1SJouni Malinen 	}
570772299f1SJouni Malinen 
571d86e5828SJouni Malinen 	if (sigma_dut_is_ap(dut)) {
572d86e5828SJouni Malinen 		if (!dut->hostapd_ifname) {
573d86e5828SJouni Malinen 			sigma_dut_print(dut, DUT_MSG_ERROR,
574d86e5828SJouni Malinen 					"hostapd ifname not specified (-j)");
575d86e5828SJouni Malinen 			return -2;
576d86e5828SJouni Malinen 		}
577d86e5828SJouni Malinen 		ifname = dut->hostapd_ifname;
578d86e5828SJouni Malinen 
579d86e5828SJouni Malinen 		if (dpp_hostapd_run(dut) < 0) {
580d86e5828SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
581d86e5828SJouni Malinen 				  "errorCode,Failed to start hostapd");
582d86e5828SJouni Malinen 			return 0;
583d86e5828SJouni Malinen 		}
584d86e5828SJouni Malinen 	}
585d86e5828SJouni Malinen 
58667acb0cfSJouni Malinen 	if (strcasecmp(prov_role, "Configurator") == 0 ||
58767acb0cfSJouni Malinen 	    strcasecmp(prov_role, "Both") == 0) {
588d86e5828SJouni Malinen 		if (dut->dpp_conf_id < 0) {
589d86e5828SJouni Malinen 			snprintf(buf, sizeof(buf),
590d86e5828SJouni Malinen 				 "DPP_CONFIGURATOR_ADD curve=%s",
591d86e5828SJouni Malinen 				 dpp_get_curve(cmd, "DPPSigningKeyECC"));
592d86e5828SJouni Malinen 			if (wpa_command_resp(ifname, buf,
593d86e5828SJouni Malinen 					     buf, sizeof(buf)) < 0) {
594d86e5828SJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
595d86e5828SJouni Malinen 					  "errorCode,Failed to set up configurator");
596d86e5828SJouni Malinen 				return 0;
597d86e5828SJouni Malinen 			}
598d86e5828SJouni Malinen 			dut->dpp_conf_id = atoi(buf);
599d86e5828SJouni Malinen 		}
60067acb0cfSJouni Malinen 		if (strcasecmp(prov_role, "Configurator") == 0)
601d86e5828SJouni Malinen 			role = "configurator";
60267acb0cfSJouni Malinen 		else
60367acb0cfSJouni Malinen 			role = "either";
604d86e5828SJouni Malinen 	} else if (strcasecmp(prov_role, "Enrollee") == 0) {
605d86e5828SJouni Malinen 		role = "enrollee";
606d86e5828SJouni Malinen 	} else {
607d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
608d86e5828SJouni Malinen 			  "errorCode,Unknown DPPProvisioningRole");
609d86e5828SJouni Malinen 		return 0;
610d86e5828SJouni Malinen 	}
611d86e5828SJouni Malinen 
612d86e5828SJouni Malinen 	pkex_identifier[0] = '\0';
613d86e5828SJouni Malinen 	if (strcasecmp(bs, "PKEX") == 0) {
6144f47a272SJouni Malinen 		if (sigma_dut_is_ap(dut) && dut->ap_channel != 6) {
6154f47a272SJouni Malinen 			/* For now, have to make operating channel match DPP
6164f47a272SJouni Malinen 			 * listen channel. This should be removed once hostapd
6174f47a272SJouni Malinen 			 * has support for DPP listen on non-operating channel.
6184f47a272SJouni Malinen 			 */
6194f47a272SJouni Malinen 			sigma_dut_print(dut, DUT_MSG_INFO,
6204f47a272SJouni Malinen 					"Update hostapd operating channel to match listen needs");
6214f47a272SJouni Malinen 			dut->ap_channel = 6;
6224f47a272SJouni Malinen 			if (wpa_command(ifname, "SET channel 6") < 0 ||
6234f47a272SJouni Malinen 			    wpa_command(ifname, "DISABLE") < 0 ||
6244f47a272SJouni Malinen 			    wpa_command(ifname, "ENABLE") < 0) {
6254f47a272SJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
6264f47a272SJouni Malinen 					  "errorCode,Failed to update channel");
6274f47a272SJouni Malinen 				return 0;
6284f47a272SJouni Malinen 			}
6294f47a272SJouni Malinen 		}
6304f47a272SJouni Malinen 
631d86e5828SJouni Malinen 		if (!pkex_code) {
632d86e5828SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
633d86e5828SJouni Malinen 				  "errorCode,Missing DPPPKEXCode");
634d86e5828SJouni Malinen 			return 0;
635d86e5828SJouni Malinen 		}
636d86e5828SJouni Malinen 
637d86e5828SJouni Malinen 		if (pkex_code_id)
638d86e5828SJouni Malinen 			snprintf(pkex_identifier, sizeof(pkex_identifier),
639d86e5828SJouni Malinen 				 "identifier=%s ", pkex_code_id);
640d86e5828SJouni Malinen 
641d86e5828SJouni Malinen 		snprintf(buf, sizeof(buf),
642d86e5828SJouni Malinen 			 "DPP_BOOTSTRAP_GEN type=pkex curve=%s",
643d86e5828SJouni Malinen 			 dpp_get_curve(cmd, "DPPCryptoIdentifier"));
644d86e5828SJouni Malinen 		if (wpa_command_resp(ifname, buf, buf, sizeof(buf)) < 0) {
645d86e5828SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
646d86e5828SJouni Malinen 				  "errorCode,Failed to set up PKEX");
647d86e5828SJouni Malinen 			return 0;
648d86e5828SJouni Malinen 		}
649d86e5828SJouni Malinen 		own_pkex_id = atoi(buf);
650d86e5828SJouni Malinen 	}
651d86e5828SJouni Malinen 
652d86e5828SJouni Malinen 	ctrl = open_wpa_mon(ifname);
653d86e5828SJouni Malinen 	if (!ctrl) {
654d86e5828SJouni Malinen 		sigma_dut_print(dut, DUT_MSG_ERROR,
655d86e5828SJouni Malinen 				"Failed to open wpa_supplicant monitor connection");
656d86e5828SJouni Malinen 		return -2;
657d86e5828SJouni Malinen 	}
658d86e5828SJouni Malinen 
659d86e5828SJouni Malinen 	old_timeout = dut->default_timeout;
660d86e5828SJouni Malinen 	val = get_param(cmd, "DPPTimeout");
661d86e5828SJouni Malinen 	if (val && atoi(val) > 0) {
662d86e5828SJouni Malinen 		dut->default_timeout = atoi(val);
663d86e5828SJouni Malinen 		sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP timeout: %u",
664d86e5828SJouni Malinen 				dut->default_timeout);
665d86e5828SJouni Malinen 	}
666d86e5828SJouni Malinen 
667d86e5828SJouni Malinen 	conf_ssid[0] = '\0';
668d86e5828SJouni Malinen 	conf_pass[0] = '\0';
669d86e5828SJouni Malinen 	val = get_param(cmd, "DPPConfIndex");
670d86e5828SJouni Malinen 	if (val)
671d86e5828SJouni Malinen 		conf_index = atoi(val);
672d86e5828SJouni Malinen 	val = get_param(cmd, "DPPConfEnrolleeRole");
673d86e5828SJouni Malinen 	switch (conf_index) {
674258cc26aSJouni Malinen 	case -1:
675258cc26aSJouni Malinen 		conf_role = NULL;
676258cc26aSJouni Malinen 		break;
677d86e5828SJouni Malinen 	case 1:
678d86e5828SJouni Malinen 		ascii2hexstr("DPPNET01", buf);
679d86e5828SJouni Malinen 		snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
6803d291f70SJouni Malinen 		if (val && strcasecmp(val, "AP") == 0) {
681d86e5828SJouni Malinen 			conf_role = "ap-dpp";
6823d291f70SJouni Malinen 			groups_override = "[{\"groupId\":\"DPPGROUP_DPP_INFRA\",\"netRole\":\"ap\"}]";
6833d291f70SJouni Malinen 		} else {
684d86e5828SJouni Malinen 			conf_role = "sta-dpp";
6853d291f70SJouni Malinen 			groups_override = "[{\"groupId\":\"DPPGROUP_DPP_INFRA\",\"netRole\":\"sta\"}]";
6863d291f70SJouni Malinen 		}
687d86e5828SJouni Malinen 		break;
688d86e5828SJouni Malinen 	case 2:
689d86e5828SJouni Malinen 		ascii2hexstr("DPPNET01", buf);
690d86e5828SJouni Malinen 		snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
6918f81cdfaSJouni Malinen 		snprintf(conf_pass, sizeof(conf_pass),
6928f81cdfaSJouni Malinen 			 "psk=10506e102ad1e7f95112f6b127675bb8344dacacea60403f3fa4055aec85b0fc");
693d86e5828SJouni Malinen 		if (val && strcasecmp(val, "AP") == 0)
694d86e5828SJouni Malinen 			conf_role = "ap-psk";
695d86e5828SJouni Malinen 		else
696d86e5828SJouni Malinen 			conf_role = "sta-psk";
697d86e5828SJouni Malinen 		break;
698d86e5828SJouni Malinen 	case 3:
699d86e5828SJouni Malinen 		ascii2hexstr("DPPNET01", buf);
700d86e5828SJouni Malinen 		snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
701d86e5828SJouni Malinen 		ascii2hexstr("ThisIsDppPassphrase", buf);
702d86e5828SJouni Malinen 		snprintf(conf_pass, sizeof(conf_pass), "pass=%s", buf);
703d86e5828SJouni Malinen 		if (val && strcasecmp(val, "AP") == 0)
704d86e5828SJouni Malinen 			conf_role = "ap-psk";
705d86e5828SJouni Malinen 		else
706d86e5828SJouni Malinen 			conf_role = "sta-psk";
707d86e5828SJouni Malinen 		break;
7083d291f70SJouni Malinen 	case 4:
7093d291f70SJouni Malinen 		ascii2hexstr("DPPNET01", buf);
7103d291f70SJouni Malinen 		snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
7113d291f70SJouni Malinen 		if (val && strcasecmp(val, "AP") == 0) {
7123d291f70SJouni Malinen 			conf_role = "ap-dpp";
7133d291f70SJouni Malinen 			groups_override = "[{\"groupId\":\"DPPGROUP_DPP_INFRA2\",\"netRole\":\"ap\"}]";
7143d291f70SJouni Malinen 		} else {
7153d291f70SJouni Malinen 			conf_role = "sta-dpp";
7163d291f70SJouni Malinen 			groups_override = "[{\"groupId\":\"DPPGROUP_DPP_INFRA2\",\"netRole\":\"sta\"}]";
7173d291f70SJouni Malinen 		}
7183d291f70SJouni Malinen 		break;
719f7490768SJouni Malinen 	default:
720f7490768SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
721f7490768SJouni Malinen 			  "errorCode,Unsupported DPPConfIndex");
722f7490768SJouni Malinen 		goto out;
723d86e5828SJouni Malinen 	}
724d86e5828SJouni Malinen 
7253d291f70SJouni Malinen 	if (groups_override) {
7263d291f70SJouni Malinen 		snprintf(buf, sizeof(buf), "SET dpp_groups_override %s",
7273d291f70SJouni Malinen 			 groups_override);
7283d291f70SJouni Malinen 		if (wpa_command(ifname, buf) < 0) {
7293d291f70SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
7303d291f70SJouni Malinen 				  "errorCode,Failed to set cred:groups");
7313d291f70SJouni Malinen 			goto out;
7323d291f70SJouni Malinen 		}
7333d291f70SJouni Malinen 	}
7343d291f70SJouni Malinen 
735772299f1SJouni Malinen 	if (step) {
736772299f1SJouni Malinen 		int test;
737772299f1SJouni Malinen 
738772299f1SJouni Malinen 		test = dpp_get_test(step, frametype, attr);
739772299f1SJouni Malinen 		if (test <= 0) {
740772299f1SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
741772299f1SJouni Malinen 				  "errorCode,Unsupported DPPStep/DPPFrameType/DPPIEAttribute");
742772299f1SJouni Malinen 			goto out;
743772299f1SJouni Malinen 		}
744772299f1SJouni Malinen 
745772299f1SJouni Malinen 		snprintf(buf, sizeof(buf), "SET dpp_test %d", test);
746772299f1SJouni Malinen 		if (wpa_command(ifname, buf) < 0) {
747772299f1SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
748772299f1SJouni Malinen 				  "errorCode,Failed to set dpp_test");
749772299f1SJouni Malinen 			goto out;
750772299f1SJouni Malinen 		}
751772299f1SJouni Malinen 	} else {
752772299f1SJouni Malinen 		wpa_command(ifname, "SET dpp_test 0");
753772299f1SJouni Malinen 	}
754772299f1SJouni Malinen 
755fbb268d7SJouni Malinen 	if (strcasecmp(self_conf, "Yes") == 0) {
756fbb268d7SJouni Malinen 		if (strcasecmp(prov_role, "Configurator") != 0) {
757fbb268d7SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
758fbb268d7SJouni Malinen 				  "errorCode,Invalid DPPSelfConfigure use - only allowed for Configurator role");
759fbb268d7SJouni Malinen 			goto out;
760fbb268d7SJouni Malinen 		}
761fbb268d7SJouni Malinen 		if (!conf_role) {
762fbb268d7SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
763fbb268d7SJouni Malinen 				  "errorCode,Missing DPPConfIndex");
764fbb268d7SJouni Malinen 			goto out;
765fbb268d7SJouni Malinen 		}
766fbb268d7SJouni Malinen 
767fbb268d7SJouni Malinen 		snprintf(buf, sizeof(buf),
768fbb268d7SJouni Malinen 			 "DPP_CONFIGURATOR_SIGN  conf=%s %s %s configurator=%d",
769fbb268d7SJouni Malinen 			 conf_role, conf_ssid, conf_pass, dut->dpp_conf_id);
770fbb268d7SJouni Malinen 		if (wpa_command(ifname, buf) < 0) {
771fbb268d7SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
772fbb268d7SJouni Malinen 				  "errorCode,Failed to initiate DPP self-configuration");
773fbb268d7SJouni Malinen 			goto out;
774fbb268d7SJouni Malinen 		}
775*174db64fSJouni Malinen 		if (sigma_dut_is_ap(dut))
776*174db64fSJouni Malinen 			goto update_ap;
777fbb268d7SJouni Malinen 		goto wait_connect;
778fbb268d7SJouni Malinen 	} else if (strcasecmp(auth_role, "Initiator") == 0) {
779d86e5828SJouni Malinen 		char own_txt[20];
780b1dd21f8SJouni Malinen 		int dpp_peer_bootstrap = -1;
781b5ab828bSJouni Malinen 		char neg_freq[30];
782b5ab828bSJouni Malinen 
783b5ab828bSJouni Malinen 		neg_freq[0] = '\0';
784b5ab828bSJouni Malinen 		val = get_param(cmd, "DPPSubsequentChannel");
785b5ab828bSJouni Malinen 		if (val) {
786b5ab828bSJouni Malinen 			int opclass, channel, freq;
787b5ab828bSJouni Malinen 
788b5ab828bSJouni Malinen 			opclass = atoi(val);
789b5ab828bSJouni Malinen 			val = strchr(val, '/');
790b5ab828bSJouni Malinen 			if (opclass == 0 || !val) {
791b5ab828bSJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
792b5ab828bSJouni Malinen 					  "errorCode,Invalid DPPSubsequentChannel");
793b5ab828bSJouni Malinen 				goto out;
794b5ab828bSJouni Malinen 			}
795b5ab828bSJouni Malinen 			val++;
796b5ab828bSJouni Malinen 			channel = atoi(val);
797b5ab828bSJouni Malinen 
798b5ab828bSJouni Malinen 			/* Ignoring opclass for now; could use it here for more
799b5ab828bSJouni Malinen 			 * robust frequency determination. */
800b5ab828bSJouni Malinen 			freq = channel_to_freq(channel);
801b5ab828bSJouni Malinen 			if (!freq) {
802b5ab828bSJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
803b5ab828bSJouni Malinen 					  "errorCode,Unsupported DPPSubsequentChannel channel");
804b5ab828bSJouni Malinen 				goto out;
805b5ab828bSJouni Malinen 			}
806b5ab828bSJouni Malinen 			snprintf(neg_freq, sizeof(neg_freq), " neg_freq=%d",
807b5ab828bSJouni Malinen 				 freq);
808b5ab828bSJouni Malinen 		}
809b1dd21f8SJouni Malinen 
810b1dd21f8SJouni Malinen 		if (strcasecmp(bs, "QR") == 0) {
811b1dd21f8SJouni Malinen 			if (!dut->dpp_peer_uri) {
812b1dd21f8SJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
813b1dd21f8SJouni Malinen 					  "errorCode,Missing peer bootstrapping info");
814b1dd21f8SJouni Malinen 				goto out;
815b1dd21f8SJouni Malinen 			}
816b1dd21f8SJouni Malinen 
817b1dd21f8SJouni Malinen 			snprintf(buf, sizeof(buf), "DPP_QR_CODE %s",
818b1dd21f8SJouni Malinen 				 dut->dpp_peer_uri);
819b1dd21f8SJouni Malinen 			if (wpa_command_resp(ifname, buf, buf,
820b1dd21f8SJouni Malinen 					     sizeof(buf)) < 0) {
821b1dd21f8SJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
822b1dd21f8SJouni Malinen 					  "errorCode,Failed to parse URI");
823b1dd21f8SJouni Malinen 				goto out;
824b1dd21f8SJouni Malinen 			}
825b1dd21f8SJouni Malinen 			dpp_peer_bootstrap = atoi(buf);
826b1dd21f8SJouni Malinen 		}
827d86e5828SJouni Malinen 
82863d5041cSJouni Malinen 		if (dut->dpp_local_bootstrap >= 0)
829d86e5828SJouni Malinen 			snprintf(own_txt, sizeof(own_txt), " own=%d",
830d86e5828SJouni Malinen 				 dut->dpp_local_bootstrap);
831d86e5828SJouni Malinen 		else
832d86e5828SJouni Malinen 			own_txt[0] = '\0';
833d86e5828SJouni Malinen 		if (strcasecmp(bs, "QR") == 0 &&
83467acb0cfSJouni Malinen 		    (strcasecmp(prov_role, "Configurator") == 0 ||
83567acb0cfSJouni Malinen 		     strcasecmp(prov_role, "Both") == 0)) {
836258cc26aSJouni Malinen 			if (!conf_role) {
837258cc26aSJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
838258cc26aSJouni Malinen 					  "errorCode,Missing DPPConfIndex");
839258cc26aSJouni Malinen 				goto out;
840258cc26aSJouni Malinen 			}
841d86e5828SJouni Malinen 			snprintf(buf, sizeof(buf),
842b5ab828bSJouni Malinen 				 "DPP_AUTH_INIT peer=%d%s role=%s conf=%s %s %s configurator=%d%s",
843b1dd21f8SJouni Malinen 				 dpp_peer_bootstrap, own_txt, role,
844d86e5828SJouni Malinen 				 conf_role, conf_ssid, conf_pass,
845b5ab828bSJouni Malinen 				 dut->dpp_conf_id, neg_freq);
846d86e5828SJouni Malinen 		} else if (strcasecmp(bs, "QR") == 0) {
847d86e5828SJouni Malinen 			snprintf(buf, sizeof(buf),
848b5ab828bSJouni Malinen 				 "DPP_AUTH_INIT peer=%d%s role=%s%s",
849b5ab828bSJouni Malinen 				 dpp_peer_bootstrap, own_txt, role, neg_freq);
850d86e5828SJouni Malinen 		} else if (strcasecmp(bs, "PKEX") == 0 &&
85167acb0cfSJouni Malinen 			   (strcasecmp(prov_role, "Configurator") == 0 ||
85267acb0cfSJouni Malinen 			    strcasecmp(prov_role, "Both") == 0)) {
853258cc26aSJouni Malinen 			if (!conf_role) {
854258cc26aSJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
855258cc26aSJouni Malinen 					  "errorCode,Missing DPPConfIndex");
856258cc26aSJouni Malinen 				goto out;
857258cc26aSJouni Malinen 			}
858d86e5828SJouni Malinen 			snprintf(buf, sizeof(buf),
859d86e5828SJouni Malinen 				 "DPP_PKEX_ADD own=%d init=1 role=%s conf=%s %s %s configurator=%d %scode=%s",
860d86e5828SJouni Malinen 				 own_pkex_id, role, conf_role,
861d86e5828SJouni Malinen 				 conf_ssid, conf_pass, dut->dpp_conf_id,
862d86e5828SJouni Malinen 				 pkex_identifier, pkex_code);
863d86e5828SJouni Malinen 		} else if (strcasecmp(bs, "PKEX") == 0) {
864d86e5828SJouni Malinen 			snprintf(buf, sizeof(buf),
865d86e5828SJouni Malinen 				 "DPP_PKEX_ADD own=%d init=1 role=%s %scode=%s",
866d86e5828SJouni Malinen 				 own_pkex_id, role, pkex_identifier, pkex_code);
867d551c6fcSJouni Malinen 		} else {
868d551c6fcSJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
869d551c6fcSJouni Malinen 				  "errorCode,Unsupported DPPBS");
870d551c6fcSJouni Malinen 			goto out;
871d86e5828SJouni Malinen 		}
872d86e5828SJouni Malinen 		if (wpa_command(ifname, buf) < 0) {
873d86e5828SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
874d86e5828SJouni Malinen 				  "errorCode,Failed to initiate DPP authentication");
875d86e5828SJouni Malinen 			goto out;
876d86e5828SJouni Malinen 		}
877d86e5828SJouni Malinen 	} else if (strcasecmp(auth_role, "Responder") == 0) {
87867f096aaSJouni Malinen 		const char *delay_qr_resp;
87963d5041cSJouni Malinen 		int mutual;
880d3afc5cbSJouni Malinen 		int freq = 2462; /* default: channel 11 */
881d3afc5cbSJouni Malinen 
88267f096aaSJouni Malinen 		delay_qr_resp = get_param(cmd, "DPPDelayQRResponse");
88367f096aaSJouni Malinen 
88463d5041cSJouni Malinen 		val = get_param(cmd, "DPPAuthDirection");
88563d5041cSJouni Malinen 		mutual = val && strcasecmp(val, "Mutual") == 0;
88663d5041cSJouni Malinen 
887d3afc5cbSJouni Malinen 		val = get_param(cmd, "DPPListenChannel");
888d3afc5cbSJouni Malinen 		if (val) {
889d3afc5cbSJouni Malinen 			freq = channel_to_freq(atoi(val));
890d3afc5cbSJouni Malinen 			if (freq == 0) {
891d3afc5cbSJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
892d3afc5cbSJouni Malinen 					  "errorCode,Unsupported DPPListenChannel value");
893d3afc5cbSJouni Malinen 				goto out;
894d3afc5cbSJouni Malinen 			}
895d3afc5cbSJouni Malinen 		}
896d86e5828SJouni Malinen 
897b1dd21f8SJouni Malinen 		if (!delay_qr_resp && dut->dpp_peer_uri) {
898b1dd21f8SJouni Malinen 			snprintf(buf, sizeof(buf), "DPP_QR_CODE %s",
899b1dd21f8SJouni Malinen 				 dut->dpp_peer_uri);
900b1dd21f8SJouni Malinen 			if (wpa_command_resp(ifname, buf, buf,
901b1dd21f8SJouni Malinen 					     sizeof(buf)) < 0) {
902b1dd21f8SJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
903b1dd21f8SJouni Malinen 					  "errorCode,Failed to parse URI");
904b1dd21f8SJouni Malinen 				goto out;
905b1dd21f8SJouni Malinen 			}
906b1dd21f8SJouni Malinen 		}
907b1dd21f8SJouni Malinen 
908d86e5828SJouni Malinen 		if (strcasecmp(prov_role, "Configurator") == 0) {
909258cc26aSJouni Malinen 			if (!conf_role) {
910258cc26aSJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
911258cc26aSJouni Malinen 					  "errorCode,Missing DPPConfIndex");
912258cc26aSJouni Malinen 				goto out;
913258cc26aSJouni Malinen 			}
914d86e5828SJouni Malinen 			snprintf(buf, sizeof(buf),
915d86e5828SJouni Malinen 				 "SET dpp_configurator_params  conf=%s %s %s configurator=%d",
916d86e5828SJouni Malinen 				 conf_role, conf_ssid, conf_pass,
917d86e5828SJouni Malinen 				 dut->dpp_conf_id);
918d86e5828SJouni Malinen 			if (wpa_command(ifname, buf) < 0) {
919d86e5828SJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
920d86e5828SJouni Malinen 					  "errorCode,Failed to set configurator parameters");
921d86e5828SJouni Malinen 				goto out;
922d86e5828SJouni Malinen 			}
923d86e5828SJouni Malinen 		}
924d86e5828SJouni Malinen 		if (strcasecmp(bs, "PKEX") == 0) {
925d86e5828SJouni Malinen 			freq = 2437;
926d86e5828SJouni Malinen 
927d86e5828SJouni Malinen 			snprintf(buf, sizeof(buf),
928d86e5828SJouni Malinen 				 "DPP_PKEX_ADD own=%d role=%s %scode=%s",
929d86e5828SJouni Malinen 				 own_pkex_id, role, pkex_identifier, pkex_code);
930d86e5828SJouni Malinen 			if (wpa_command(ifname, buf) < 0) {
931d86e5828SJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
932d86e5828SJouni Malinen 					  "errorCode,Failed to configure DPP PKEX");
933d86e5828SJouni Malinen 				goto out;
934d86e5828SJouni Malinen 			}
935d86e5828SJouni Malinen 		}
936d86e5828SJouni Malinen 
937fd7359aeSJouni Malinen 		snprintf(buf, sizeof(buf), "DPP_LISTEN %d role=%s%s",
938fd7359aeSJouni Malinen 			 freq, role,
939fd7359aeSJouni Malinen 			 (strcasecmp(bs, "QR") == 0 && mutual) ?
940fd7359aeSJouni Malinen 			 " qr=mutual" : "");
941d86e5828SJouni Malinen 		if (wpa_command(ifname, buf) < 0) {
942d86e5828SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
943d86e5828SJouni Malinen 				  "errorCode,Failed to start DPP listen");
944d86e5828SJouni Malinen 			goto out;
945d86e5828SJouni Malinen 		}
946b1dd21f8SJouni Malinen 
947b1dd21f8SJouni Malinen 		if (delay_qr_resp && mutual && dut->dpp_peer_uri) {
948b1dd21f8SJouni Malinen 			int wait_time = atoi(delay_qr_resp);
949b1dd21f8SJouni Malinen 
950b1dd21f8SJouni Malinen 			res = get_wpa_cli_events(dut, ctrl, auth_events,
951b1dd21f8SJouni Malinen 						 buf, sizeof(buf));
952b1dd21f8SJouni Malinen 			if (res < 0) {
953b1dd21f8SJouni Malinen 				send_resp(dut, conn, SIGMA_COMPLETE,
954b1dd21f8SJouni Malinen 					  "BootstrapResult,OK,AuthResult,Timeout");
955b1dd21f8SJouni Malinen 				goto out;
956b1dd21f8SJouni Malinen 			}
957b1dd21f8SJouni Malinen 			sigma_dut_print(dut, DUT_MSG_DEBUG,
958b1dd21f8SJouni Malinen 					"DPP auth result: %s", buf);
959b1dd21f8SJouni Malinen 			if (strstr(buf, "DPP-SCAN-PEER-QR-CODE") == NULL) {
960b1dd21f8SJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
961b1dd21f8SJouni Malinen 					  "errorCode,No scan request for peer QR Code seen");
962b1dd21f8SJouni Malinen 				goto out;
963b1dd21f8SJouni Malinen 			}
964b1dd21f8SJouni Malinen 			sigma_dut_print(dut, DUT_MSG_INFO,
965b1dd21f8SJouni Malinen 					"Waiting %d second(s) before processing peer URI",
966b1dd21f8SJouni Malinen 					wait_time);
967b1dd21f8SJouni Malinen 			sleep(wait_time);
968b1dd21f8SJouni Malinen 
969b1dd21f8SJouni Malinen 			snprintf(buf, sizeof(buf), "DPP_QR_CODE %s",
970b1dd21f8SJouni Malinen 				 dut->dpp_peer_uri);
971b1dd21f8SJouni Malinen 			if (wpa_command_resp(ifname, buf, buf,
972b1dd21f8SJouni Malinen 					     sizeof(buf)) < 0) {
973b1dd21f8SJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
974b1dd21f8SJouni Malinen 					  "errorCode,Failed to parse URI");
975b1dd21f8SJouni Malinen 				goto out;
976b1dd21f8SJouni Malinen 			}
977b1dd21f8SJouni Malinen 		}
978d86e5828SJouni Malinen 	} else {
979d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
980d86e5828SJouni Malinen 			  "errorCode,Unknown DPPAuthRole");
981d86e5828SJouni Malinen 		goto out;
982d86e5828SJouni Malinen 	}
983d86e5828SJouni Malinen 
984772299f1SJouni Malinen 	if (frametype && strcasecmp(frametype, "PKEXExchangeRequest") == 0) {
985772299f1SJouni Malinen 		if (dpp_wait_tx_status(dut, ctrl, 7) < 0)
986772299f1SJouni Malinen 			result = "BootstrapResult,Timeout";
987772299f1SJouni Malinen 		else
988772299f1SJouni Malinen 			result = "BootstrapResult,Errorsent";
989772299f1SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, result);
990772299f1SJouni Malinen 		goto out;
991772299f1SJouni Malinen 	}
992772299f1SJouni Malinen 
993772299f1SJouni Malinen 	if (frametype && strcasecmp(frametype, "PKEXExchangeResponse") == 0) {
994772299f1SJouni Malinen 		if (dpp_wait_tx_status(dut, ctrl, 8) < 0)
995772299f1SJouni Malinen 			result = "BootstrapResult,Timeout";
996772299f1SJouni Malinen 		else
997772299f1SJouni Malinen 			result = "BootstrapResult,Errorsent";
998772299f1SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, result);
999772299f1SJouni Malinen 		goto out;
1000772299f1SJouni Malinen 	}
1001772299f1SJouni Malinen 
1002772299f1SJouni Malinen 	if (frametype && strcasecmp(frametype, "PKEXCRRequest") == 0) {
1003772299f1SJouni Malinen 		if (dpp_wait_tx_status(dut, ctrl, 9) < 0)
1004772299f1SJouni Malinen 			result = "BootstrapResult,Timeout";
1005772299f1SJouni Malinen 		else
1006772299f1SJouni Malinen 			result = "BootstrapResult,Errorsent";
1007772299f1SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, result);
1008772299f1SJouni Malinen 		goto out;
1009772299f1SJouni Malinen 	}
1010772299f1SJouni Malinen 
1011772299f1SJouni Malinen 	if (frametype && strcasecmp(frametype, "PKEXCRResponse") == 0) {
1012772299f1SJouni Malinen 		if (dpp_wait_tx_status(dut, ctrl, 10) < 0)
1013772299f1SJouni Malinen 			result = "BootstrapResult,Timeout";
1014772299f1SJouni Malinen 		else
1015772299f1SJouni Malinen 			result = "BootstrapResult,Errorsent";
1016772299f1SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, result);
1017772299f1SJouni Malinen 		goto out;
1018772299f1SJouni Malinen 	}
1019772299f1SJouni Malinen 
1020772299f1SJouni Malinen 	if (frametype && strcasecmp(frametype, "AuthenticationRequest") == 0) {
1021772299f1SJouni Malinen 		if (dpp_wait_tx_status(dut, ctrl, 0) < 0)
1022772299f1SJouni Malinen 			result = "BootstrapResult,OK,AuthResult,Timeout";
1023772299f1SJouni Malinen 		else
1024772299f1SJouni Malinen 			result = "BootstrapResult,OK,AuthResult,Errorsent";
1025772299f1SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, result);
1026772299f1SJouni Malinen 		goto out;
1027772299f1SJouni Malinen 	}
1028772299f1SJouni Malinen 
1029772299f1SJouni Malinen 	if (frametype && strcasecmp(frametype, "AuthenticationResponse") == 0) {
1030772299f1SJouni Malinen 		if (dpp_wait_tx_status(dut, ctrl, 1) < 0)
1031772299f1SJouni Malinen 			result = "BootstrapResult,OK,AuthResult,Timeout";
1032772299f1SJouni Malinen 		else
1033772299f1SJouni Malinen 			result = "BootstrapResult,OK,AuthResult,Errorsent";
1034772299f1SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, result);
1035772299f1SJouni Malinen 		goto out;
1036772299f1SJouni Malinen 	}
1037772299f1SJouni Malinen 
1038772299f1SJouni Malinen 	if (frametype && strcasecmp(frametype, "AuthenticationConfirm") == 0) {
1039772299f1SJouni Malinen 		if (dpp_wait_tx_status(dut, ctrl, 2) < 0)
1040772299f1SJouni Malinen 			result = "BootstrapResult,OK,AuthResult,Timeout";
1041772299f1SJouni Malinen 		else
1042772299f1SJouni Malinen 			result = "BootstrapResult,OK,AuthResult,Errorsent";
1043772299f1SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, result);
1044772299f1SJouni Malinen 		goto out;
1045772299f1SJouni Malinen 	}
1046772299f1SJouni Malinen 
1047d86e5828SJouni Malinen 	res = get_wpa_cli_events(dut, ctrl, auth_events, buf, sizeof(buf));
1048d86e5828SJouni Malinen 	if (res < 0) {
1049d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE,
1050d86e5828SJouni Malinen 			  "BootstrapResult,OK,AuthResult,Timeout");
1051d86e5828SJouni Malinen 		goto out;
1052d86e5828SJouni Malinen 	}
1053d86e5828SJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP auth result: %s", buf);
1054d86e5828SJouni Malinen 
10552e9c8a46SJouni Malinen 	if (strstr(buf, "DPP-RESPONSE-PENDING")) {
10562e9c8a46SJouni Malinen 		/* Wait for the actual result after the peer has scanned the
10572e9c8a46SJouni Malinen 		 * QR Code. */
10582e9c8a46SJouni Malinen 		res = get_wpa_cli_events(dut, ctrl, auth_events,
10592e9c8a46SJouni Malinen 					 buf, sizeof(buf));
10602e9c8a46SJouni Malinen 		if (res < 0) {
10612e9c8a46SJouni Malinen 			send_resp(dut, conn, SIGMA_COMPLETE,
10622e9c8a46SJouni Malinen 				  "BootstrapResult,OK,AuthResult,Timeout");
10632e9c8a46SJouni Malinen 			goto out;
10642e9c8a46SJouni Malinen 		}
10652e9c8a46SJouni Malinen 	}
10662e9c8a46SJouni Malinen 
1067d86e5828SJouni Malinen 	if (strstr(buf, "DPP-NOT-COMPATIBLE")) {
1068d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE,
1069d86e5828SJouni Malinen 			  "BootstrapResult,OK,AuthResult,ROLES_NOT_COMPATIBLE");
1070d86e5828SJouni Malinen 		goto out;
1071d86e5828SJouni Malinen 	}
1072d86e5828SJouni Malinen 
1073d86e5828SJouni Malinen 	if (!strstr(buf, "DPP-AUTH-SUCCESS")) {
1074d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE,
1075d86e5828SJouni Malinen 			  "BootstrapResult,OK,AuthResult,FAILED");
1076d86e5828SJouni Malinen 		goto out;
1077d86e5828SJouni Malinen 	}
1078d86e5828SJouni Malinen 
1079772299f1SJouni Malinen 	if (frametype && strcasecmp(frametype, "ConfigurationRequest") == 0) {
1080772299f1SJouni Malinen 		res = get_wpa_cli_event(dut, ctrl, "GAS-QUERY-DONE",
1081772299f1SJouni Malinen 					buf, sizeof(buf));
1082772299f1SJouni Malinen 		if (res < 0)
1083772299f1SJouni Malinen 			result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Timeout";
1084772299f1SJouni Malinen 		else
1085772299f1SJouni Malinen 			result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Errorsent";
1086772299f1SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, result);
1087772299f1SJouni Malinen 		goto out;
1088772299f1SJouni Malinen 	}
1089772299f1SJouni Malinen 
1090772299f1SJouni Malinen 	if (frametype && strcasecmp(frametype, "ConfigurationResponse") == 0) {
1091772299f1SJouni Malinen 		res = get_wpa_cli_event(dut, ctrl, "DPP-CONF-SENT",
1092772299f1SJouni Malinen 					buf, sizeof(buf));
1093772299f1SJouni Malinen 		if (res < 0)
1094772299f1SJouni Malinen 			result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Timeout";
1095772299f1SJouni Malinen 		else
1096772299f1SJouni Malinen 			result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Errorsent";
1097772299f1SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, result);
1098772299f1SJouni Malinen 		goto out;
1099772299f1SJouni Malinen 	}
1100772299f1SJouni Malinen 
1101d86e5828SJouni Malinen 	res = get_wpa_cli_events(dut, ctrl, conf_events, buf, sizeof(buf));
1102d86e5828SJouni Malinen 	if (res < 0) {
1103d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE,
1104d86e5828SJouni Malinen 			  "BootstrapResult,OK,AuthResult,OK,ConfResult,Timeout");
1105d86e5828SJouni Malinen 		goto out;
1106d86e5828SJouni Malinen 	}
1107d86e5828SJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP conf result: %s", buf);
1108d86e5828SJouni Malinen 
1109d86e5828SJouni Malinen 	if (!strstr(buf, "DPP-CONF-SENT") &&
1110d86e5828SJouni Malinen 	    !strstr(buf, "DPP-CONF-RECEIVED")) {
1111d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE,
1112d86e5828SJouni Malinen 			  "BootstrapResult,OK,AuthResult,OK,ConfResult,FAILED");
1113d86e5828SJouni Malinen 		goto out;
1114d86e5828SJouni Malinen 	}
1115d86e5828SJouni Malinen 
1116d86e5828SJouni Malinen 	if (sigma_dut_is_ap(dut) &&
1117d86e5828SJouni Malinen 	    strcasecmp(prov_role, "Enrollee") == 0) {
1118*174db64fSJouni Malinen 	update_ap:
1119d86e5828SJouni Malinen 		res = dpp_hostapd_conf_update(dut, conn, ifname, ctrl);
1120d86e5828SJouni Malinen 		if (res == 0)
1121d86e5828SJouni Malinen 			goto out;
1122d86e5828SJouni Malinen 		if (res < 0) {
1123d86e5828SJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR, NULL);
1124d86e5828SJouni Malinen 			goto out;
1125d86e5828SJouni Malinen 		}
1126d86e5828SJouni Malinen 	}
1127d86e5828SJouni Malinen 
1128d86e5828SJouni Malinen 	if (strcasecmp(wait_conn, "Yes") == 0 &&
1129d86e5828SJouni Malinen 	    !sigma_dut_is_ap(dut) &&
1130d86e5828SJouni Malinen 	    strcasecmp(prov_role, "Enrollee") == 0) {
1131fbb268d7SJouni Malinen 	wait_connect:
113253558e0fSJouni Malinen 		if (frametype && strcasecmp(frametype,
113353558e0fSJouni Malinen 					    "PeerDiscoveryRequest") == 0) {
113453558e0fSJouni Malinen 			if (dpp_wait_tx_status(dut, ctrl, 5) < 0)
113553558e0fSJouni Malinen 				result = "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Timeout";
113653558e0fSJouni Malinen 			else
113753558e0fSJouni Malinen 				result = "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Errorsent";
113853558e0fSJouni Malinen 			send_resp(dut, conn, SIGMA_COMPLETE, result);
113953558e0fSJouni Malinen 			goto out;
114053558e0fSJouni Malinen 		}
114153558e0fSJouni Malinen 
1142d86e5828SJouni Malinen 		res = get_wpa_cli_events(dut, ctrl, conn_events,
1143d86e5828SJouni Malinen 					 buf, sizeof(buf));
1144d86e5828SJouni Malinen 		if (res < 0) {
1145d86e5828SJouni Malinen 			send_resp(dut, conn, SIGMA_COMPLETE,
1146d86e5828SJouni Malinen 				  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Timeout,NetworkConnectResult,Timeout");
1147d86e5828SJouni Malinen 			goto out;
1148d86e5828SJouni Malinen 		}
1149d86e5828SJouni Malinen 		sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP connect result: %s",
1150d86e5828SJouni Malinen 				buf);
1151d86e5828SJouni Malinen 
1152d86e5828SJouni Malinen 		if (strstr(buf, "PMKSA-CACHE-ADDED")) {
1153d86e5828SJouni Malinen 			res = get_wpa_cli_events(dut, ctrl, conn_events,
1154d86e5828SJouni Malinen 						 buf, sizeof(buf));
1155d86e5828SJouni Malinen 			if (res < 0) {
1156d86e5828SJouni Malinen 				send_resp(dut, conn, SIGMA_COMPLETE,
1157d86e5828SJouni Malinen 					  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,OK,NetworkConnectResult,Timeout");
1158d86e5828SJouni Malinen 				goto out;
1159d86e5828SJouni Malinen 			}
1160d86e5828SJouni Malinen 			sigma_dut_print(dut, DUT_MSG_DEBUG,
1161d86e5828SJouni Malinen 					"DPP connect result: %s", buf);
1162d86e5828SJouni Malinen 			if (strstr(buf, "CTRL-EVENT-CONNECTED"))
1163d86e5828SJouni Malinen 				send_resp(dut, conn, SIGMA_COMPLETE,
1164d86e5828SJouni Malinen 					  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,OK,NetworkConnectResult,OK");
1165d86e5828SJouni Malinen 			else
1166d86e5828SJouni Malinen 				send_resp(dut, conn, SIGMA_COMPLETE,
1167d86e5828SJouni Malinen 					  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,OK,NetworkConnectResult,Timeout");
1168d86e5828SJouni Malinen 			goto out;
1169d86e5828SJouni Malinen 		}
1170d86e5828SJouni Malinen 
1171d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE,
1172d86e5828SJouni Malinen 			  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkConnectResult,OK");
1173d86e5828SJouni Malinen 		goto out;
1174d86e5828SJouni Malinen 	}
1175d86e5828SJouni Malinen 
117653558e0fSJouni Malinen 	if (strcasecmp(wait_conn, "Yes") == 0 &&
117753558e0fSJouni Malinen 	    frametype && strcasecmp(frametype, "PeerDiscoveryResponse") == 0) {
117853558e0fSJouni Malinen 		if (dpp_wait_tx_status(dut, ctrl, 6) < 0)
117953558e0fSJouni Malinen 			result = "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Timeout";
118053558e0fSJouni Malinen 		else
118153558e0fSJouni Malinen 			result = "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Errorsent";
118253558e0fSJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, result);
118353558e0fSJouni Malinen 		goto out;
118453558e0fSJouni Malinen 	}
118553558e0fSJouni Malinen 
1186d86e5828SJouni Malinen 	send_resp(dut, conn, SIGMA_COMPLETE,
1187d86e5828SJouni Malinen 		  "BootstrapResult,OK,AuthResult,OK,ConfResult,OK");
1188d86e5828SJouni Malinen out:
1189d86e5828SJouni Malinen 	wpa_ctrl_detach(ctrl);
1190d86e5828SJouni Malinen 	wpa_ctrl_close(ctrl);
1191d86e5828SJouni Malinen 	dut->default_timeout = old_timeout;
1192d86e5828SJouni Malinen 	return 0;
1193d86e5828SJouni Malinen }
1194d86e5828SJouni Malinen 
1195d86e5828SJouni Malinen 
1196d86e5828SJouni Malinen int dpp_dev_exec_action(struct sigma_dut *dut, struct sigma_conn *conn,
1197d86e5828SJouni Malinen 			struct sigma_cmd *cmd)
1198d86e5828SJouni Malinen {
1199d86e5828SJouni Malinen 	const char *type = get_param(cmd, "DPPActionType");
1200d86e5828SJouni Malinen 	const char *bs = get_param(cmd, "DPPBS");
1201d86e5828SJouni Malinen 
1202d86e5828SJouni Malinen 	if (!bs) {
1203d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
1204d86e5828SJouni Malinen 			  "errorCode,Missing DPPBS");
1205d86e5828SJouni Malinen 		return 0;
1206d86e5828SJouni Malinen 	}
1207d86e5828SJouni Malinen 
1208d86e5828SJouni Malinen 	if (!type) {
1209d86e5828SJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
1210d86e5828SJouni Malinen 			  "errorCode,Missing DPPActionType");
1211d86e5828SJouni Malinen 		return 0;
1212d86e5828SJouni Malinen 	}
1213d86e5828SJouni Malinen 
1214d86e5828SJouni Malinen 	if (strcasecmp(type, "GetLocalBootstrap") == 0)
1215d86e5828SJouni Malinen 		return dpp_get_local_bootstrap(dut, conn, cmd);
1216d86e5828SJouni Malinen 	if (strcasecmp(type, "SetPeerBootstrap") == 0)
1217d86e5828SJouni Malinen 		return dpp_set_peer_bootstrap(dut, conn, cmd);
1218d86e5828SJouni Malinen 	if (strcasecmp(type, "ManualDPP") == 0)
1219d86e5828SJouni Malinen 		return dpp_manual_dpp(dut, conn, cmd);
1220d86e5828SJouni Malinen 	if (strcasecmp(type, "AutomaticDPP") == 0)
1221d86e5828SJouni Malinen 		return dpp_automatic_dpp(dut, conn, cmd);
1222d86e5828SJouni Malinen 
1223d86e5828SJouni Malinen 	send_resp(dut, conn, SIGMA_ERROR,
1224d86e5828SJouni Malinen 		  "errorCode,Unsupported DPPActionType");
1225d86e5828SJouni Malinen 	return 0;
1226d86e5828SJouni Malinen }
1227