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