blob: 56ad9d68c42b8f9353178329077891f93f01c574 [file] [log] [blame]
Jouni Malinend86e5822017-08-29 03:55:32 +03001/*
2 * Sigma Control API DUT (station/AP/sniffer)
3 * Copyright (c) 2017, Qualcomm Atheros, Inc.
4 * All Rights Reserved.
5 * Licensed under the Clear BSD license. See README for more details.
6 */
7
8#include "sigma_dut.h"
9#include "wpa_ctrl.h"
10#include "wpa_helpers.h"
11
12
13static int sigma_dut_is_ap(struct sigma_dut *dut)
14{
15 return dut->device_type == AP_unknown ||
16 dut->device_type == AP_testbed ||
17 dut->device_type == AP_dut;
18}
19
20
21static int dpp_hostapd_run(struct sigma_dut *dut)
22{
23 if (dut->hostapd_running)
24 return 0;
25
26 sigma_dut_print(dut, DUT_MSG_INFO,
27 "Starting hostapd in unconfigured state for DPP");
28 snprintf(dut->ap_ssid, sizeof(dut->ap_ssid), "unconfigured");
29 dut->ap_channel = 11;
30 dut->ap_is_dual = 0;
31 dut->ap_mode = AP_11ng;
32 dut->ap_key_mgmt = AP_OPEN;
33 dut->ap_cipher = AP_PLAIN;
34 return cmd_ap_config_commit(dut, NULL, NULL) == 1 ? 0 : -1;
35}
36
37
38static const char * dpp_get_curve(struct sigma_cmd *cmd, const char *arg)
39{
40 const char *val = get_param(cmd, arg);
41
42 if (!val)
43 val = "P-256";
44 else if (strcasecmp(val, "BP-256R1") == 0)
45 val = "BP-256";
46 else if (strcasecmp(val, "BP-384R1") == 0)
47 val = "BP-384";
48 else if (strcasecmp(val, "BP-512R1") == 0)
49 val = "BP-512";
50
51 return val;
52}
53
54
55static int dpp_get_local_bootstrap(struct sigma_dut *dut,
56 struct sigma_conn *conn,
57 struct sigma_cmd *cmd)
58{
59 const char *curve = dpp_get_curve(cmd, "DPPCryptoIdentifier");
60 const char *bs = get_param(cmd, "DPPBS");
Jouni Malinen4161c3f2017-11-13 18:36:09 +020061 const char *chan_list = get_param(cmd, "DPPChannelList");
62 char *pos, mac[50], buf[200], resp[1000], hex[2000];
Jouni Malinend86e5822017-08-29 03:55:32 +030063 const char *ifname = get_station_ifname();
64
65 if (strcasecmp(bs, "QR") != 0) {
66 send_resp(dut, conn, SIGMA_ERROR,
67 "errorCode,Unsupported DPPBS");
68 return 0;
69 }
70
71 if (sigma_dut_is_ap(dut)) {
72 u8 bssid[ETH_ALEN];
73
74 if (!dut->hostapd_ifname) {
75 sigma_dut_print(dut, DUT_MSG_ERROR,
76 "hostapd ifname not specified (-j)");
77 return -2;
78 }
79 ifname = dut->hostapd_ifname;
80 if (get_hwaddr(dut->hostapd_ifname, bssid) < 0) {
81 sigma_dut_print(dut, DUT_MSG_ERROR,
82 "Could not get MAC address for %s",
83 dut->hostapd_ifname);
84 return -2;
85 }
86 snprintf(mac, sizeof(mac), "%02x%02x%02x%02x%02x%02x",
87 bssid[0], bssid[1], bssid[2],
88 bssid[3], bssid[4], bssid[5]);
89 } else {
90 if (get_wpa_status(ifname, "address", mac, sizeof(mac)) < 0)
91 return -2;
92 }
93
94 pos = mac;
95 while (*pos) {
96 if (*pos == ':')
97 memmove(pos, pos + 1, strlen(pos));
98 else
99 pos++;
100 }
101
Jouni Malinend86e5822017-08-29 03:55:32 +0300102 if (sigma_dut_is_ap(dut) && dpp_hostapd_run(dut) < 0) {
103 send_resp(dut, conn, SIGMA_ERROR,
104 "errorCode,Failed to start hostapd");
105 return 0;
106 }
107
Jouni Malinen4161c3f2017-11-13 18:36:09 +0200108 if (chan_list &&
109 (strcmp(chan_list, "0/0") == 0 || chan_list[0] == '\0')) {
110 /* No channel list */
111 snprintf(buf, sizeof(buf),
112 "DPP_BOOTSTRAP_GEN type=qrcode curve=%s mac=%s",
113 curve, mac);
114 } else if (chan_list) {
115 /* Channel list override (CTT case) - space separated tuple(s)
116 * of OperatingClass/Channel; convert to wpa_supplicant/hostapd
117 * format: comma separated tuples */
118 strlcpy(resp, chan_list, sizeof(resp));
119 for (pos = resp; *pos; pos++) {
120 if (*pos == ' ')
121 *pos = ',';
122 }
123 snprintf(buf, sizeof(buf),
124 "DPP_BOOTSTRAP_GEN type=qrcode curve=%s chan=%s mac=%s",
125 curve, resp, mac);
126 } else {
127 /* Default channel list (normal DUT case) */
128 snprintf(buf, sizeof(buf),
129 "DPP_BOOTSTRAP_GEN type=qrcode curve=%s chan=81/11 mac=%s",
130 curve, mac);
131 }
132
Jouni Malinend86e5822017-08-29 03:55:32 +0300133 if (wpa_command_resp(ifname, buf, resp, sizeof(resp)) < 0)
134 return -2;
135 if (strncmp(resp, "FAIL", 4) == 0)
136 return -2;
137 dut->dpp_local_bootstrap = atoi(resp);
138 snprintf(buf, sizeof(buf), "DPP_BOOTSTRAP_GET_URI %d",
139 atoi(resp));
140 if (wpa_command_resp(ifname, buf, resp, sizeof(resp)) < 0)
141 return -2;
142 if (strncmp(resp, "FAIL", 4) == 0)
143 return -2;
144
145 sigma_dut_print(dut, DUT_MSG_DEBUG, "URI: %s", resp);
146 ascii2hexstr(resp, hex);
147 snprintf(resp, sizeof(resp), "BootstrappingData,%s", hex);
148 send_resp(dut, conn, SIGMA_COMPLETE, resp);
149 return 0;
150}
151
152
153static int dpp_set_peer_bootstrap(struct sigma_dut *dut,
154 struct sigma_conn *conn,
155 struct sigma_cmd *cmd)
156{
157 const char *val = get_param(cmd, "DPPBootstrappingdata");
Jouni Malinenb1dd21f2017-11-13 19:14:29 +0200158 char uri[1000];
Jouni Malinend86e5822017-08-29 03:55:32 +0300159 int res;
Jouni Malinend86e5822017-08-29 03:55:32 +0300160
161 if (!val) {
162 send_resp(dut, conn, SIGMA_ERROR,
163 "errorCode,Missing DPPBootstrappingdata");
164 return 0;
165 }
166
167 res = parse_hexstr(val, (unsigned char *) uri, sizeof(uri));
168 if (res < 0 || (size_t) res >= sizeof(uri))
169 return -2;
170 uri[res] = '\0';
171 sigma_dut_print(dut, DUT_MSG_DEBUG, "URI: %s", uri);
Jouni Malinenb1dd21f2017-11-13 19:14:29 +0200172 free(dut->dpp_peer_uri);
173 dut->dpp_peer_uri = strdup(uri);
Jouni Malinend86e5822017-08-29 03:55:32 +0300174
175 return 1;
176}
177
178
179static int dpp_hostapd_conf_update(struct sigma_dut *dut,
180 struct sigma_conn *conn, const char *ifname,
181 struct wpa_ctrl *ctrl)
182{
183 int res;
184 char buf[2000], buf2[2500], *pos, *pos2;
Jouni Malinenb4c5e3b2017-09-15 17:43:20 +0300185 const char *conf_data_events[] = {
186 "DPP-CONNECTOR",
187 "DPP-CONFOBJ-PASS",
188 "DPP-CONFOBJ-PSK",
189 NULL
190 };
Jouni Malinend86e5822017-08-29 03:55:32 +0300191
192 sigma_dut_print(dut, DUT_MSG_INFO,
193 "Update hostapd configuration based on DPP Config Object");
194
195 if (wpa_command(ifname, "SET wpa 2") < 0 ||
196 wpa_command(ifname, "SET wpa_key_mgmt DPP") < 0 ||
Jouni Malinen0d347232017-11-01 17:14:00 +0200197 wpa_command(ifname, "SET ieee80211w 1") < 0 ||
Jouni Malinend86e5822017-08-29 03:55:32 +0300198 wpa_command(ifname, "SET rsn_pairwise CCMP") < 0) {
199 send_resp(dut, conn, SIGMA_ERROR,
200 "errorCode,Failed to update AP security parameters");
201 goto out;
202 }
203
204 res = get_wpa_cli_event(dut, ctrl, "DPP-CONFOBJ-SSID",
205 buf, sizeof(buf));
206 if (res < 0) {
207 send_resp(dut, conn, SIGMA_ERROR,
208 "errorCode,No DPP-CONFOBJ-SSID");
209 goto out;
210 }
211 pos = strchr(buf, ' ');
212 if (!pos)
213 return -2;
214 pos++;
215 sigma_dut_print(dut, DUT_MSG_INFO,
216 "DPP: Config Object SSID: %s", pos);
217 snprintf(buf2, sizeof(buf2), "SET ssid %s", pos);
218 if (wpa_command(ifname, buf2) < 0) {
219 send_resp(dut, conn, SIGMA_ERROR,
220 "errorCode,Failed to update AP SSID");
221 goto out;
222 }
223
Jouni Malinenb4c5e3b2017-09-15 17:43:20 +0300224 res = get_wpa_cli_events(dut, ctrl, conf_data_events, buf, sizeof(buf));
Jouni Malinend86e5822017-08-29 03:55:32 +0300225 if (res < 0) {
226 send_resp(dut, conn, SIGMA_ERROR,
Jouni Malinenb4c5e3b2017-09-15 17:43:20 +0300227 "errorCode,No DPP-CONNECTOR/DPP-CONFOBJ-PASS/PSK");
Jouni Malinend86e5822017-08-29 03:55:32 +0300228 goto out;
229 }
Jouni Malinenb4c5e3b2017-09-15 17:43:20 +0300230
231 if (!strstr(buf, "DPP-CONNECTOR")) {
232 if (wpa_command(ifname, "SET wpa_key_mgmt WPA-PSK") < 0) {
233 send_resp(dut, conn, SIGMA_ERROR,
234 "errorCode,Failed to update AP security parameters");
235 goto out;
236 }
237
238 pos = strchr(buf, ' ');
239 if (!pos)
240 return -2;
241 pos++;
242 if (strstr(buf, "DPP-CONFOBJ-PASS")) {
243 char pass[64];
244 int pass_len;
245
246 pass_len = parse_hexstr(pos, (u8 *) pass, sizeof(pass));
247 if (pass_len < 0 || pass_len >= sizeof(pass))
248 return -2;
249 pass[pass_len] = '\0';
250 sigma_dut_print(dut, DUT_MSG_INFO,
251 "DPP: Passphrase: %s", pass);
252 snprintf(buf2, sizeof(buf2), "SET wpa_passphrase %s",
253 pass);
254 if (wpa_command(ifname, buf2) < 0) {
255 send_resp(dut, conn, SIGMA_ERROR,
256 "errorCode,Failed to set passphrase");
257 goto out;
258 }
259 } else if (strstr(buf, "DPP-CONFOBJ-PSK")) {
260 sigma_dut_print(dut, DUT_MSG_INFO,
261 "DPP: PSK: %s", pos);
262 snprintf(buf2, sizeof(buf2), "SET wpa_psk %s", pos);
263 if (wpa_command(ifname, buf2) < 0) {
264 send_resp(dut, conn, SIGMA_ERROR,
265 "errorCode,Failed to set PSK");
266 goto out;
267 }
268 }
269
270 goto skip_dpp_akm;
271 }
272
Jouni Malinend86e5822017-08-29 03:55:32 +0300273 pos = strchr(buf, ' ');
274 if (!pos)
275 return -2;
276 pos++;
277 sigma_dut_print(dut, DUT_MSG_INFO, "DPP: Connector: %s", pos);
278 snprintf(buf2, sizeof(buf2), "SET dpp_connector %s", pos);
279 if (wpa_command(ifname, buf2) < 0) {
280 send_resp(dut, conn, SIGMA_ERROR,
281 "errorCode,Failed to update AP Connector");
282 goto out;
283 }
284
285 res = get_wpa_cli_event(dut, ctrl, "DPP-C-SIGN-KEY",
286 buf, sizeof(buf));
287 if (res < 0) {
288 send_resp(dut, conn, SIGMA_ERROR,
289 "errorCode,No DPP-C-SIGN-KEY");
290 goto out;
291 }
292 pos = strchr(buf, ' ');
293 if (!pos)
294 return -2;
295 pos++;
Jouni Malinend86e5822017-08-29 03:55:32 +0300296 sigma_dut_print(dut, DUT_MSG_INFO, "DPP: C-sign-key: %s", pos);
297 snprintf(buf2, sizeof(buf2), "SET dpp_csign %s", pos);
298 if (wpa_command(ifname, buf2) < 0) {
299 send_resp(dut, conn, SIGMA_ERROR,
300 "errorCode,Failed to update AP C-sign-key");
301 goto out;
302 }
Jouni Malinend86e5822017-08-29 03:55:32 +0300303
304 res = get_wpa_cli_event(dut, ctrl, "DPP-NET-ACCESS-KEY",
305 buf, sizeof(buf));
306 if (res < 0) {
307 send_resp(dut, conn, SIGMA_ERROR,
308 "errorCode,No DPP-NET-ACCESS-KEY");
309 goto out;
310 }
311 pos = strchr(buf, ' ');
312 if (!pos)
313 return -2;
314 pos++;
315 pos2 = strchr(pos, ' ');
316 if (pos2)
317 *pos2++ = '\0';
318 sigma_dut_print(dut, DUT_MSG_INFO, "DPP: netAccessKey: %s", pos);
319 snprintf(buf2, sizeof(buf2), "SET dpp_netaccesskey %s", pos);
320 if (wpa_command(ifname, buf2) < 0) {
321 send_resp(dut, conn, SIGMA_ERROR,
322 "errorCode,Failed to update AP netAccessKey");
323 goto out;
324 }
325 if (pos2) {
326 sigma_dut_print(dut, DUT_MSG_INFO,
327 "DPP: netAccessKey expiry: %s", pos2);
328 snprintf(buf2, sizeof(buf2), "SET dpp_netaccesskey_expiry %s",
329 pos2);
330 if (wpa_command(ifname, buf2) < 0) {
331 send_resp(dut, conn, SIGMA_ERROR,
332 "errorCode,Failed to update AP netAccessKey expiry");
333 goto out;
334 }
335 }
Jouni Malinenb4c5e3b2017-09-15 17:43:20 +0300336skip_dpp_akm:
Jouni Malinend86e5822017-08-29 03:55:32 +0300337
338 if (wpa_command(ifname, "DISABLE") < 0 ||
339 wpa_command(ifname, "ENABLE") < 0) {
340 send_resp(dut, conn, SIGMA_ERROR,
341 "errorCode,Failed to update AP configuration");
342 goto out;
343 }
344
345 res = get_wpa_cli_event(dut, ctrl, "AP-ENABLED", buf, sizeof(buf));
346 if (res < 0) {
347 send_resp(dut, conn, SIGMA_ERROR, "errorCode,No AP-ENABLED");
348 goto out;
349 }
350
351 return 1;
352out:
353 return 0;
354}
355
356
Jouni Malinen772299f2017-11-06 00:36:26 +0200357struct dpp_test_info {
358 const char *step;
359 const char *frame;
360 const char *attr;
361 int value;
362};
363
364static const struct dpp_test_info dpp_tests[] = {
365 { "InvalidValue", "AuthenticationRequest", "WrappedData", 1 },
366 { "InvalidValue", "AuthenticationResponse", "WrappedData", 2 },
Jouni Malinenf96fcee2017-11-22 16:08:35 +0200367 { "InvalidValue", "AuthenticationResponse", "PrimaryWrappedData", 2 },
Jouni Malinen772299f2017-11-06 00:36:26 +0200368 { "InvalidValue", "AuthenticationConfirm", "WrappedData", 3 },
369 { "InvalidValue", "PKEXCRRequest", "WrappedData", 4 },
370 { "InvalidValue", "PKEXCRResponse", "WrappedData", 5 },
371 { "InvalidValue", "ConfigurationRequest", "WrappedData", 6 },
372 { "InvalidValue", "ConfigurationResponse", "WrappedData", 7 },
373 { "InvalidValue", "AuthenticationRequest", "InitCapabilities", 8 },
Jouni Malinen772299f2017-11-06 00:36:26 +0200374 { "MissingAttribute", "AuthenticationRequest", "RespBSKeyHash", 10 },
375 { "MissingAttribute", "AuthenticationRequest", "InitBSKeyHash", 11 },
376 { "MissingAttribute", "AuthenticationRequest", "InitProtocolKey", 12 },
377 { "MissingAttribute", "AuthenticationRequest", "InitNonce", 13 },
378 { "MissingAttribute", "AuthenticationRequest", "InitCapabilities", 14 },
379 { "MissingAttribute", "AuthenticationRequest", "WrappedData", 15 },
380 { "MissingAttribute", "AuthenticationResponse", "DPPStatus", 16 },
381 { "MissingAttribute", "AuthenticationResponse", "RespBSKeyHash", 17 },
382 { "MissingAttribute", "AuthenticationResponse", "InitBSKeyHash", 18 },
383 { "MissingAttribute", "AuthenticationResponse", "RespProtocolKey", 19 },
384 { "MissingAttribute", "AuthenticationResponse", "RespNonce", 20 },
385 { "MissingAttribute", "AuthenticationResponse", "InitNonce", 21 },
386 { "MissingAttribute", "AuthenticationResponse", "RespCapabilities",
387 22 },
388 { "MissingAttribute", "AuthenticationResponse", "RespAuthTag", 23 },
389 { "MissingAttribute", "AuthenticationResponse", "WrappedData", 24 },
Jouni Malinenf96fcee2017-11-22 16:08:35 +0200390 { "MissingAttribute", "AuthenticationResponse", "PrimaryWrappedData",
391 24 },
Jouni Malinen772299f2017-11-06 00:36:26 +0200392 { "MissingAttribute", "AuthenticationConfirm", "DPPStatus", 25 },
393 { "MissingAttribute", "AuthenticationConfirm", "RespBSKeyHash", 26 },
394 { "MissingAttribute", "AuthenticationConfirm", "InitBSKeyHash", 27 },
395 { "MissingAttribute", "AuthenticationConfirm", "InitAuthTag", 28 },
396 { "MissingAttribute", "AuthenticationConfirm", "WrappedData", 29 },
397 { "InvalidValue", "AuthenticationResponse", "InitNonce", 30 },
398 { "InvalidValue", "AuthenticationResponse", "RespCapabilities", 31 },
399 { "InvalidValue", "AuthenticationResponse", "RespAuthTag", 32 },
400 { "InvalidValue", "AuthenticationConfirm", "InitAuthTag", 33 },
401 { "MissingAttribute", "PKEXExchangeRequest", "FiniteCyclicGroup", 34 },
402 { "MissingAttribute", "PKEXExchangeRequest", "EncryptedKey", 35 },
403 { "MissingAttribute", "PKEXExchangeResponse", "DPPStatus", 36 },
404 { "MissingAttribute", "PKEXExchangeResponse", "EncryptedKey", 37 },
405 { "MissingAttribute", "PKEXCRRequest", "BSKey", 38 },
406 { "MissingAttribute", "PKEXCRRequest", "InitAuthTag", 39 },
407 { "MissingAttribute", "PKEXCRRequest", "WrappedData", 40 },
408 { "MissingAttribute", "PKEXCRResponse", "BSKey", 41 },
409 { "MissingAttribute", "PKEXCRResponse", "RespAuthTag", 42 },
410 { "MissingAttribute", "PKEXCRResponse", "WrappedData", 43 },
411 { "InvalidValue", "PKEXExchangeRequest", "EncryptedKey", 44 },
412 { "InvalidValue", "PKEXExchangeResponse", "EncryptedKey", 45 },
413 { "InvalidValue", "PKEXExchangeResponse", "DPPStatus", 46 },
414 { "InvalidValue", "PKEXCRRequest", "BSKey", 47 },
415 { "InvalidValue", "PKEXCRResponse", "BSKey", 48 },
416 { "InvalidValue", "PKEXCRRequest", "InitAuthTag", 49 },
417 { "InvalidValue", "PKEXCRResponse", "RespAuthTag", 50 },
418 { "MissingAttribute", "ConfigurationRequest", "EnrolleeNonce", 51 },
419 { "MissingAttribute", "ConfigurationRequest", "ConfigAttr", 52 },
420 { "MissingAttribute", "ConfigurationRequest", "WrappedData", 53 },
421 { "MissingAttribute", "ConfigurationResponse", "EnrolleeNonce", 54 },
422 { "MissingAttribute", "ConfigurationResponse", "ConfigObj", 55 },
423 { "MissingAttribute", "ConfigurationResponse", "DPPStatus", 56 },
424 { "MissingAttribute", "ConfigurationResponse", "WrappedData", 57 },
425 { "InvalidValue", "ConfigurationResponse", "DPPStatus", 58 },
426 { "InvalidValue", "ConfigurationResponse", "EnrolleeNonce", 59 },
Jouni Malinen53558e02017-11-06 12:58:28 +0200427 { "MissingAttribute", "PeerDiscoveryRequest", "TransactionID", 60 },
428 { "MissingAttribute", "PeerDiscoveryRequest", "Connector", 61 },
429 { "MissingAttribute", "PeerDiscoveryResponse", "TransactionID", 62 },
430 { "MissingAttribute", "PeerDiscoveryResponse", "DPPStatus", 63 },
431 { "MissingAttribute", "PeerDiscoveryResponse", "Connector", 64 },
Jouni Malinenae624482017-11-19 00:13:51 +0200432 { "InvalidValue", "AuthenticationRequest", "InitProtocolKey", 66 },
433 { "InvalidValue", "AuthenticationResponse", "RespProtocolKey", 67 },
434 { "InvalidValue", "AuthenticationRequest", "RespBSKeyHash", 68 },
435 { "InvalidValue", "AuthenticationRequest", "InitBSKeyHash", 69 },
436 { "InvalidValue", "AuthenticationResponse", "RespBSKeyHash", 70 },
437 { "InvalidValue", "AuthenticationResponse", "InitBSKeyHash", 71 },
438 { "InvalidValue", "AuthenticationConfirm", "RespBSKeyHash", 72 },
439 { "InvalidValue", "AuthenticationConfirm", "InitBSKeyHash", 73 },
440 { "InvalidValue", "AuthenticationResponse", "DPPStatus", 74 },
441 { "InvalidValue", "AuthenticationConfirm", "DPPStatus", 75 },
442 { "InvalidValue", "ConfigurationRequest", "ConfigAttr", 76 },
443 { "InvalidValue", "PeerDiscoveryResponse", "TransactionID", 77 },
444 { "InvalidValue", "PeerDiscoveryResponse", "DPPStatus", 78 },
445 { "InvalidValue", "PeerDiscoveryResponse", "Connector", 79 },
446 { "InvalidValue", "PeerDiscoveryRequest", "Connector", 80 },
Jouni Malinen67795a72017-11-22 16:24:43 +0200447 { "InvalidValue", "AuthenticationRequest", "InitNonce", 81 },
Jouni Malinen188839b2017-11-30 22:02:02 +0200448 { "InvalidValue", "PeerDiscoveryRequest", "TransactionID", 82 },
449 { "InvalidValue", "ConfigurationRequest", "EnrolleeNonce", 83 },
Jouni Malinen3a6b92a2017-12-05 20:22:43 +0200450 { "Timeout", "PKEXExchangeResponse", NULL, 84 },
451 { "Timeout", "PKEXCRRequest", NULL, 85 },
452 { "Timeout", "PKEXCRResponse", NULL, 86 },
453 { "Timeout", "AuthenticationRequest", NULL, 87 },
454 { "Timeout", "AuthenticationResponse", NULL, 88 },
455 { "Timeout", "AuthenticationConfirm", NULL, 89 },
456 { "Timeout", "ConfigurationRequest", NULL, 90 },
Jouni Malinen772299f2017-11-06 00:36:26 +0200457 { NULL, NULL, NULL, 0 }
458};
459
460
461static int dpp_get_test(const char *step, const char *frame, const char *attr)
462{
463 int i;
464
465 for (i = 0; dpp_tests[i].step; i++) {
466 if (strcasecmp(step, dpp_tests[i].step) == 0 &&
467 strcasecmp(frame, dpp_tests[i].frame) == 0 &&
Jouni Malinen3a6b92a2017-12-05 20:22:43 +0200468 ((!attr && dpp_tests[i].attr == NULL) ||
469 (attr && strcasecmp(attr, dpp_tests[i].attr) == 0)))
Jouni Malinen772299f2017-11-06 00:36:26 +0200470 return dpp_tests[i].value;
471 }
472
473 return -1;
474}
475
476
477static int dpp_wait_tx_status(struct sigma_dut *dut, struct wpa_ctrl *ctrl,
478 int frame_type)
479{
480 char buf[200], tmp[20];
481 int res;
482
483 snprintf(tmp, sizeof(tmp), "type=%d", frame_type);
484 for (;;) {
485 res = get_wpa_cli_event(dut, ctrl, "DPP-TX", buf, sizeof(buf));
486 if (res < 0)
487 return -1;
488 if (strstr(buf, tmp) != NULL)
489 break;
490 }
491
492 res = get_wpa_cli_event(dut, ctrl, "DPP-TX-STATUS",
493 buf, sizeof(buf));
494 if (res < 0 || strstr(buf, "result=FAILED") != NULL)
495 return -1;
496
497 return 0;
498}
499
500
Jouni Malinen3a6b92a2017-12-05 20:22:43 +0200501static int dpp_wait_rx(struct sigma_dut *dut, struct wpa_ctrl *ctrl,
502 int frame_type)
503{
504 char buf[200], tmp[20];
505 int res;
506
507 snprintf(tmp, sizeof(tmp), "type=%d", frame_type);
508 for (;;) {
509 res = get_wpa_cli_event(dut, ctrl, "DPP-RX", buf, sizeof(buf));
510 if (res < 0)
511 return -1;
512 if (strstr(buf, tmp) != NULL)
513 break;
514 }
515
516 return 0;
517}
518
519
Jouni Malinend86e5822017-08-29 03:55:32 +0300520static int dpp_manual_dpp(struct sigma_dut *dut,
521 struct sigma_conn *conn,
522 struct sigma_cmd *cmd)
523{
524 /* TODO */
525 return -1;
526}
527
528
529static int dpp_automatic_dpp(struct sigma_dut *dut,
530 struct sigma_conn *conn,
531 struct sigma_cmd *cmd)
532{
533 const char *bs = get_param(cmd, "DPPBS");
534 const char *auth_role = get_param(cmd, "DPPAuthRole");
535 const char *prov_role = get_param(cmd, "DPPProvisioningRole");
536 const char *pkex_code = get_param(cmd, "DPPPKEXCode");
537 const char *pkex_code_id = get_param(cmd, "DPPPKEXCodeIdentifier");
538 const char *wait_conn = get_param(cmd, "DPPWaitForConnect");
539 const char *self_conf = get_param(cmd, "DPPSelfConfigure");
Jouni Malinen772299f2017-11-06 00:36:26 +0200540 const char *step = get_param(cmd, "DPPStep");
541 const char *frametype = get_param(cmd, "DPPFrameType");
542 const char *attr = get_param(cmd, "DPPIEAttribute");
Jouni Malinend86e5822017-08-29 03:55:32 +0300543 const char *role;
544 const char *val;
545 const char *conf_role;
Jouni Malinend86e5822017-08-29 03:55:32 +0300546 int conf_index = -1;
547 char buf[2000];
548 char conf_ssid[100];
549 char conf_pass[100];
550 char pkex_identifier[200];
551 struct wpa_ctrl *ctrl;
552 int res;
553 unsigned int old_timeout;
554 int own_pkex_id = -1;
555 const char *ifname = get_station_ifname();
556 const char *auth_events[] = {
557 "DPP-AUTH-SUCCESS",
558 "DPP-NOT-COMPATIBLE",
559 "DPP-RESPONSE-PENDING",
560 "DPP-SCAN-PEER-QR-CODE",
561 NULL
562 };
563 const char *conf_events[] = {
564 "DPP-CONF-RECEIVED",
565 "DPP-CONF-SENT",
566 "DPP-CONF-FAILED",
567 NULL
568 };
569 const char *conn_events[] = {
570 "PMKSA-CACHE-ADDED",
571 "CTRL-EVENT-CONNECTED",
572 NULL
573 };
Jouni Malinen3d291f72017-11-02 11:31:05 +0200574 const char *groups_override = NULL;
Jouni Malinen772299f2017-11-06 00:36:26 +0200575 const char *result;
Jouni Malinend1e22f72017-12-05 21:12:17 +0200576 int check_mutual = 0;
Jouni Malinend86e5822017-08-29 03:55:32 +0300577
578 if (!wait_conn)
579 wait_conn = "no";
580 if (!self_conf)
581 self_conf = "no";
582
583 if (!auth_role) {
584 send_resp(dut, conn, SIGMA_ERROR,
585 "errorCode,Missing DPPAuthRole");
586 return 0;
587 }
588
589 if (!prov_role) {
590 send_resp(dut, conn, SIGMA_ERROR,
591 "errorCode,Missing DPPProvisioningRole");
592 return 0;
593 }
594
Jouni Malinen3a6b92a2017-12-05 20:22:43 +0200595 if ((step || frametype) && (!step || !frametype)) {
Jouni Malinen772299f2017-11-06 00:36:26 +0200596 send_resp(dut, conn, SIGMA_ERROR,
597 "errorCode,Invalid DPPStep,DPPFrameType,DPPIEAttribute combination");
598 return 0;
599 }
600
Jouni Malinend86e5822017-08-29 03:55:32 +0300601 if (sigma_dut_is_ap(dut)) {
602 if (!dut->hostapd_ifname) {
603 sigma_dut_print(dut, DUT_MSG_ERROR,
604 "hostapd ifname not specified (-j)");
605 return -2;
606 }
607 ifname = dut->hostapd_ifname;
608
609 if (dpp_hostapd_run(dut) < 0) {
610 send_resp(dut, conn, SIGMA_ERROR,
611 "errorCode,Failed to start hostapd");
612 return 0;
613 }
614 }
615
Jouni Malinen67acb0c2017-11-21 01:01:54 +0200616 if (strcasecmp(prov_role, "Configurator") == 0 ||
617 strcasecmp(prov_role, "Both") == 0) {
Jouni Malinend86e5822017-08-29 03:55:32 +0300618 if (dut->dpp_conf_id < 0) {
619 snprintf(buf, sizeof(buf),
620 "DPP_CONFIGURATOR_ADD curve=%s",
621 dpp_get_curve(cmd, "DPPSigningKeyECC"));
622 if (wpa_command_resp(ifname, buf,
623 buf, sizeof(buf)) < 0) {
624 send_resp(dut, conn, SIGMA_ERROR,
625 "errorCode,Failed to set up configurator");
626 return 0;
627 }
628 dut->dpp_conf_id = atoi(buf);
629 }
Jouni Malinen67acb0c2017-11-21 01:01:54 +0200630 if (strcasecmp(prov_role, "Configurator") == 0)
631 role = "configurator";
632 else
633 role = "either";
Jouni Malinend86e5822017-08-29 03:55:32 +0300634 } else if (strcasecmp(prov_role, "Enrollee") == 0) {
635 role = "enrollee";
636 } else {
637 send_resp(dut, conn, SIGMA_ERROR,
638 "errorCode,Unknown DPPProvisioningRole");
639 return 0;
640 }
641
642 pkex_identifier[0] = '\0';
643 if (strcasecmp(bs, "PKEX") == 0) {
Jouni Malinen4f47a272017-11-04 12:29:11 +0200644 if (sigma_dut_is_ap(dut) && dut->ap_channel != 6) {
645 /* For now, have to make operating channel match DPP
646 * listen channel. This should be removed once hostapd
647 * has support for DPP listen on non-operating channel.
648 */
649 sigma_dut_print(dut, DUT_MSG_INFO,
650 "Update hostapd operating channel to match listen needs");
651 dut->ap_channel = 6;
652 if (wpa_command(ifname, "SET channel 6") < 0 ||
653 wpa_command(ifname, "DISABLE") < 0 ||
654 wpa_command(ifname, "ENABLE") < 0) {
655 send_resp(dut, conn, SIGMA_ERROR,
656 "errorCode,Failed to update channel");
657 return 0;
658 }
659 }
660
Jouni Malinend86e5822017-08-29 03:55:32 +0300661 if (!pkex_code) {
662 send_resp(dut, conn, SIGMA_ERROR,
663 "errorCode,Missing DPPPKEXCode");
664 return 0;
665 }
666
667 if (pkex_code_id)
668 snprintf(pkex_identifier, sizeof(pkex_identifier),
669 "identifier=%s ", pkex_code_id);
670
671 snprintf(buf, sizeof(buf),
672 "DPP_BOOTSTRAP_GEN type=pkex curve=%s",
673 dpp_get_curve(cmd, "DPPCryptoIdentifier"));
674 if (wpa_command_resp(ifname, buf, buf, sizeof(buf)) < 0) {
675 send_resp(dut, conn, SIGMA_ERROR,
676 "errorCode,Failed to set up PKEX");
677 return 0;
678 }
679 own_pkex_id = atoi(buf);
680 }
681
682 ctrl = open_wpa_mon(ifname);
683 if (!ctrl) {
684 sigma_dut_print(dut, DUT_MSG_ERROR,
685 "Failed to open wpa_supplicant monitor connection");
686 return -2;
687 }
688
689 old_timeout = dut->default_timeout;
690 val = get_param(cmd, "DPPTimeout");
691 if (val && atoi(val) > 0) {
692 dut->default_timeout = atoi(val);
693 sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP timeout: %u",
694 dut->default_timeout);
695 }
696
697 conf_ssid[0] = '\0';
698 conf_pass[0] = '\0';
699 val = get_param(cmd, "DPPConfIndex");
700 if (val)
701 conf_index = atoi(val);
702 val = get_param(cmd, "DPPConfEnrolleeRole");
703 switch (conf_index) {
Jouni Malinen258cc262017-10-13 00:19:56 +0300704 case -1:
705 conf_role = NULL;
706 break;
Jouni Malinend86e5822017-08-29 03:55:32 +0300707 case 1:
708 ascii2hexstr("DPPNET01", buf);
709 snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
Jouni Malinen3d291f72017-11-02 11:31:05 +0200710 if (val && strcasecmp(val, "AP") == 0) {
Jouni Malinend86e5822017-08-29 03:55:32 +0300711 conf_role = "ap-dpp";
Jouni Malinen3d291f72017-11-02 11:31:05 +0200712 groups_override = "[{\"groupId\":\"DPPGROUP_DPP_INFRA\",\"netRole\":\"ap\"}]";
713 } else {
Jouni Malinend86e5822017-08-29 03:55:32 +0300714 conf_role = "sta-dpp";
Jouni Malinen3d291f72017-11-02 11:31:05 +0200715 groups_override = "[{\"groupId\":\"DPPGROUP_DPP_INFRA\",\"netRole\":\"sta\"}]";
716 }
Jouni Malinend86e5822017-08-29 03:55:32 +0300717 break;
718 case 2:
719 ascii2hexstr("DPPNET01", buf);
720 snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
Jouni Malinen8f81cdf2017-09-15 18:15:18 +0300721 snprintf(conf_pass, sizeof(conf_pass),
722 "psk=10506e102ad1e7f95112f6b127675bb8344dacacea60403f3fa4055aec85b0fc");
Jouni Malinend86e5822017-08-29 03:55:32 +0300723 if (val && strcasecmp(val, "AP") == 0)
724 conf_role = "ap-psk";
725 else
726 conf_role = "sta-psk";
727 break;
728 case 3:
729 ascii2hexstr("DPPNET01", buf);
730 snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
731 ascii2hexstr("ThisIsDppPassphrase", buf);
732 snprintf(conf_pass, sizeof(conf_pass), "pass=%s", buf);
733 if (val && strcasecmp(val, "AP") == 0)
734 conf_role = "ap-psk";
735 else
736 conf_role = "sta-psk";
737 break;
Jouni Malinen3d291f72017-11-02 11:31:05 +0200738 case 4:
739 ascii2hexstr("DPPNET01", buf);
740 snprintf(conf_ssid, sizeof(conf_ssid), "ssid=%s", buf);
741 if (val && strcasecmp(val, "AP") == 0) {
742 conf_role = "ap-dpp";
743 groups_override = "[{\"groupId\":\"DPPGROUP_DPP_INFRA2\",\"netRole\":\"ap\"}]";
744 } else {
745 conf_role = "sta-dpp";
746 groups_override = "[{\"groupId\":\"DPPGROUP_DPP_INFRA2\",\"netRole\":\"sta\"}]";
747 }
748 break;
Jouni Malinenf7490762017-10-12 00:34:37 +0300749 default:
750 send_resp(dut, conn, SIGMA_ERROR,
751 "errorCode,Unsupported DPPConfIndex");
752 goto out;
Jouni Malinend86e5822017-08-29 03:55:32 +0300753 }
754
Jouni Malinen3d291f72017-11-02 11:31:05 +0200755 if (groups_override) {
756 snprintf(buf, sizeof(buf), "SET dpp_groups_override %s",
757 groups_override);
758 if (wpa_command(ifname, buf) < 0) {
759 send_resp(dut, conn, SIGMA_ERROR,
760 "errorCode,Failed to set cred:groups");
761 goto out;
762 }
763 }
764
Jouni Malinen772299f2017-11-06 00:36:26 +0200765 if (step) {
766 int test;
767
768 test = dpp_get_test(step, frametype, attr);
769 if (test <= 0) {
770 send_resp(dut, conn, SIGMA_ERROR,
771 "errorCode,Unsupported DPPStep/DPPFrameType/DPPIEAttribute");
772 goto out;
773 }
774
775 snprintf(buf, sizeof(buf), "SET dpp_test %d", test);
776 if (wpa_command(ifname, buf) < 0) {
777 send_resp(dut, conn, SIGMA_ERROR,
778 "errorCode,Failed to set dpp_test");
779 goto out;
780 }
781 } else {
782 wpa_command(ifname, "SET dpp_test 0");
783 }
784
Jouni Malinenfbb268d2017-11-17 18:53:49 +0200785 if (strcasecmp(self_conf, "Yes") == 0) {
786 if (strcasecmp(prov_role, "Configurator") != 0) {
787 send_resp(dut, conn, SIGMA_ERROR,
788 "errorCode,Invalid DPPSelfConfigure use - only allowed for Configurator role");
789 goto out;
790 }
791 if (!conf_role) {
792 send_resp(dut, conn, SIGMA_ERROR,
793 "errorCode,Missing DPPConfIndex");
794 goto out;
795 }
796
797 snprintf(buf, sizeof(buf),
798 "DPP_CONFIGURATOR_SIGN conf=%s %s %s configurator=%d",
799 conf_role, conf_ssid, conf_pass, dut->dpp_conf_id);
800 if (wpa_command(ifname, buf) < 0) {
801 send_resp(dut, conn, SIGMA_ERROR,
802 "errorCode,Failed to initiate DPP self-configuration");
803 goto out;
804 }
Jouni Malinen174db642017-11-27 20:16:29 +0200805 if (sigma_dut_is_ap(dut))
806 goto update_ap;
Jouni Malinenfbb268d2017-11-17 18:53:49 +0200807 goto wait_connect;
808 } else if (strcasecmp(auth_role, "Initiator") == 0) {
Jouni Malinend86e5822017-08-29 03:55:32 +0300809 char own_txt[20];
Jouni Malinenb1dd21f2017-11-13 19:14:29 +0200810 int dpp_peer_bootstrap = -1;
Jouni Malinenb5ab8282017-11-21 01:12:22 +0200811 char neg_freq[30];
812
Jouni Malinend1e22f72017-12-05 21:12:17 +0200813 val = get_param(cmd, "DPPAuthDirection");
814 check_mutual = val && strcasecmp(val, "Mutual") == 0;
815
Jouni Malinenb5ab8282017-11-21 01:12:22 +0200816 neg_freq[0] = '\0';
817 val = get_param(cmd, "DPPSubsequentChannel");
818 if (val) {
819 int opclass, channel, freq;
820
821 opclass = atoi(val);
822 val = strchr(val, '/');
823 if (opclass == 0 || !val) {
824 send_resp(dut, conn, SIGMA_ERROR,
825 "errorCode,Invalid DPPSubsequentChannel");
826 goto out;
827 }
828 val++;
829 channel = atoi(val);
830
831 /* Ignoring opclass for now; could use it here for more
832 * robust frequency determination. */
833 freq = channel_to_freq(channel);
834 if (!freq) {
835 send_resp(dut, conn, SIGMA_ERROR,
836 "errorCode,Unsupported DPPSubsequentChannel channel");
837 goto out;
838 }
839 snprintf(neg_freq, sizeof(neg_freq), " neg_freq=%d",
840 freq);
841 }
Jouni Malinenb1dd21f2017-11-13 19:14:29 +0200842
843 if (strcasecmp(bs, "QR") == 0) {
844 if (!dut->dpp_peer_uri) {
845 send_resp(dut, conn, SIGMA_ERROR,
846 "errorCode,Missing peer bootstrapping info");
847 goto out;
848 }
849
850 snprintf(buf, sizeof(buf), "DPP_QR_CODE %s",
851 dut->dpp_peer_uri);
852 if (wpa_command_resp(ifname, buf, buf,
853 sizeof(buf)) < 0) {
854 send_resp(dut, conn, SIGMA_ERROR,
855 "errorCode,Failed to parse URI");
856 goto out;
857 }
858 dpp_peer_bootstrap = atoi(buf);
859 }
Jouni Malinend86e5822017-08-29 03:55:32 +0300860
Jouni Malinen63d50412017-11-24 11:55:38 +0200861 if (dut->dpp_local_bootstrap >= 0)
Jouni Malinend86e5822017-08-29 03:55:32 +0300862 snprintf(own_txt, sizeof(own_txt), " own=%d",
863 dut->dpp_local_bootstrap);
864 else
865 own_txt[0] = '\0';
866 if (strcasecmp(bs, "QR") == 0 &&
Jouni Malinen67acb0c2017-11-21 01:01:54 +0200867 (strcasecmp(prov_role, "Configurator") == 0 ||
868 strcasecmp(prov_role, "Both") == 0)) {
Jouni Malinen258cc262017-10-13 00:19:56 +0300869 if (!conf_role) {
870 send_resp(dut, conn, SIGMA_ERROR,
871 "errorCode,Missing DPPConfIndex");
872 goto out;
873 }
Jouni Malinend86e5822017-08-29 03:55:32 +0300874 snprintf(buf, sizeof(buf),
Jouni Malinenb5ab8282017-11-21 01:12:22 +0200875 "DPP_AUTH_INIT peer=%d%s role=%s conf=%s %s %s configurator=%d%s",
Jouni Malinenb1dd21f2017-11-13 19:14:29 +0200876 dpp_peer_bootstrap, own_txt, role,
Jouni Malinend86e5822017-08-29 03:55:32 +0300877 conf_role, conf_ssid, conf_pass,
Jouni Malinenb5ab8282017-11-21 01:12:22 +0200878 dut->dpp_conf_id, neg_freq);
Jouni Malinend86e5822017-08-29 03:55:32 +0300879 } else if (strcasecmp(bs, "QR") == 0) {
880 snprintf(buf, sizeof(buf),
Jouni Malinenb5ab8282017-11-21 01:12:22 +0200881 "DPP_AUTH_INIT peer=%d%s role=%s%s",
882 dpp_peer_bootstrap, own_txt, role, neg_freq);
Jouni Malinend86e5822017-08-29 03:55:32 +0300883 } else if (strcasecmp(bs, "PKEX") == 0 &&
Jouni Malinen67acb0c2017-11-21 01:01:54 +0200884 (strcasecmp(prov_role, "Configurator") == 0 ||
885 strcasecmp(prov_role, "Both") == 0)) {
Jouni Malinen258cc262017-10-13 00:19:56 +0300886 if (!conf_role) {
887 send_resp(dut, conn, SIGMA_ERROR,
888 "errorCode,Missing DPPConfIndex");
889 goto out;
890 }
Jouni Malinend86e5822017-08-29 03:55:32 +0300891 snprintf(buf, sizeof(buf),
892 "DPP_PKEX_ADD own=%d init=1 role=%s conf=%s %s %s configurator=%d %scode=%s",
893 own_pkex_id, role, conf_role,
894 conf_ssid, conf_pass, dut->dpp_conf_id,
895 pkex_identifier, pkex_code);
896 } else if (strcasecmp(bs, "PKEX") == 0) {
897 snprintf(buf, sizeof(buf),
898 "DPP_PKEX_ADD own=%d init=1 role=%s %scode=%s",
899 own_pkex_id, role, pkex_identifier, pkex_code);
Jouni Malinend551c6f2017-10-12 00:32:18 +0300900 } else {
901 send_resp(dut, conn, SIGMA_ERROR,
902 "errorCode,Unsupported DPPBS");
903 goto out;
Jouni Malinend86e5822017-08-29 03:55:32 +0300904 }
905 if (wpa_command(ifname, buf) < 0) {
906 send_resp(dut, conn, SIGMA_ERROR,
907 "errorCode,Failed to initiate DPP authentication");
908 goto out;
909 }
910 } else if (strcasecmp(auth_role, "Responder") == 0) {
Jouni Malinen67f096a2017-11-24 11:58:51 +0200911 const char *delay_qr_resp;
Jouni Malinen63d50412017-11-24 11:55:38 +0200912 int mutual;
Jouni Malinend3afc5c2017-11-13 18:39:14 +0200913 int freq = 2462; /* default: channel 11 */
914
Jouni Malinen67f096a2017-11-24 11:58:51 +0200915 delay_qr_resp = get_param(cmd, "DPPDelayQRResponse");
916
Jouni Malinen63d50412017-11-24 11:55:38 +0200917 val = get_param(cmd, "DPPAuthDirection");
918 mutual = val && strcasecmp(val, "Mutual") == 0;
919
Jouni Malinend3afc5c2017-11-13 18:39:14 +0200920 val = get_param(cmd, "DPPListenChannel");
921 if (val) {
922 freq = channel_to_freq(atoi(val));
923 if (freq == 0) {
924 send_resp(dut, conn, SIGMA_ERROR,
925 "errorCode,Unsupported DPPListenChannel value");
926 goto out;
927 }
928 }
Jouni Malinend86e5822017-08-29 03:55:32 +0300929
Jouni Malinenb1dd21f2017-11-13 19:14:29 +0200930 if (!delay_qr_resp && dut->dpp_peer_uri) {
931 snprintf(buf, sizeof(buf), "DPP_QR_CODE %s",
932 dut->dpp_peer_uri);
933 if (wpa_command_resp(ifname, buf, buf,
934 sizeof(buf)) < 0) {
935 send_resp(dut, conn, SIGMA_ERROR,
936 "errorCode,Failed to parse URI");
937 goto out;
938 }
939 }
940
Jouni Malinend86e5822017-08-29 03:55:32 +0300941 if (strcasecmp(prov_role, "Configurator") == 0) {
Jouni Malinen258cc262017-10-13 00:19:56 +0300942 if (!conf_role) {
943 send_resp(dut, conn, SIGMA_ERROR,
944 "errorCode,Missing DPPConfIndex");
945 goto out;
946 }
Jouni Malinend86e5822017-08-29 03:55:32 +0300947 snprintf(buf, sizeof(buf),
948 "SET dpp_configurator_params conf=%s %s %s configurator=%d",
949 conf_role, conf_ssid, conf_pass,
950 dut->dpp_conf_id);
951 if (wpa_command(ifname, buf) < 0) {
952 send_resp(dut, conn, SIGMA_ERROR,
953 "errorCode,Failed to set configurator parameters");
954 goto out;
955 }
956 }
957 if (strcasecmp(bs, "PKEX") == 0) {
958 freq = 2437;
959
960 snprintf(buf, sizeof(buf),
961 "DPP_PKEX_ADD own=%d role=%s %scode=%s",
962 own_pkex_id, role, pkex_identifier, pkex_code);
963 if (wpa_command(ifname, buf) < 0) {
964 send_resp(dut, conn, SIGMA_ERROR,
965 "errorCode,Failed to configure DPP PKEX");
966 goto out;
967 }
968 }
969
Jouni Malinenbafc1932017-11-04 11:31:16 +0200970 snprintf(buf, sizeof(buf), "DPP_LISTEN %d role=%s%s",
971 freq, role,
972 (strcasecmp(bs, "QR") == 0 && mutual) ?
973 " qr=mutual" : "");
974 if (wpa_command(ifname, buf) < 0) {
975 send_resp(dut, conn, SIGMA_ERROR,
976 "errorCode,Failed to start DPP listen");
977 goto out;
Jouni Malinend86e5822017-08-29 03:55:32 +0300978 }
Jouni Malinenb1dd21f2017-11-13 19:14:29 +0200979
980 if (delay_qr_resp && mutual && dut->dpp_peer_uri) {
981 int wait_time = atoi(delay_qr_resp);
982
983 res = get_wpa_cli_events(dut, ctrl, auth_events,
984 buf, sizeof(buf));
985 if (res < 0) {
986 send_resp(dut, conn, SIGMA_COMPLETE,
987 "BootstrapResult,OK,AuthResult,Timeout");
988 goto out;
989 }
990 sigma_dut_print(dut, DUT_MSG_DEBUG,
991 "DPP auth result: %s", buf);
992 if (strstr(buf, "DPP-SCAN-PEER-QR-CODE") == NULL) {
993 send_resp(dut, conn, SIGMA_ERROR,
994 "errorCode,No scan request for peer QR Code seen");
995 goto out;
996 }
997 sigma_dut_print(dut, DUT_MSG_INFO,
998 "Waiting %d second(s) before processing peer URI",
999 wait_time);
1000 sleep(wait_time);
1001
1002 snprintf(buf, sizeof(buf), "DPP_QR_CODE %s",
1003 dut->dpp_peer_uri);
1004 if (wpa_command_resp(ifname, buf, buf,
1005 sizeof(buf)) < 0) {
1006 send_resp(dut, conn, SIGMA_ERROR,
1007 "errorCode,Failed to parse URI");
1008 goto out;
1009 }
1010 }
Jouni Malinend86e5822017-08-29 03:55:32 +03001011 } else {
1012 send_resp(dut, conn, SIGMA_ERROR,
1013 "errorCode,Unknown DPPAuthRole");
1014 goto out;
1015 }
1016
Jouni Malinen3a6b92a2017-12-05 20:22:43 +02001017 if (step && strcasecmp(step, "Timeout") == 0) {
1018 result = "errorCode,Unexpected state";
1019
1020 if (strcasecmp(frametype, "PKEXExchangeResponse") == 0) {
1021 if (dpp_wait_rx(dut, ctrl, 8) < 0)
1022 result = "BootstrapResult,Timeout";
1023 else
1024 result = "BootstrapResult,Errorsent";
1025 }
1026
1027 if (strcasecmp(frametype, "PKEXCRRequest") == 0) {
1028 if (dpp_wait_rx(dut, ctrl, 9) < 0)
1029 result = "BootstrapResult,Timeout";
1030 else
1031 result = "BootstrapResult,Errorsent";
1032 }
1033
1034 if (strcasecmp(frametype, "PKEXCRResponse") == 0) {
1035 if (dpp_wait_rx(dut, ctrl, 10) < 0)
1036 result = "BootstrapResult,Timeout";
1037 else
1038 result = "BootstrapResult,Errorsent";
1039 }
1040
1041 if (strcasecmp(frametype, "AuthenticationRequest") == 0) {
1042 if (dpp_wait_rx(dut, ctrl, 0) < 0)
1043 result = "BootstrapResult,OK,AuthResult,Timeout";
1044 else
1045 result = "BootstrapResult,OK,AuthResult,Errorsent";
1046 }
1047
1048 if (strcasecmp(frametype, "AuthenticationResponse") == 0) {
1049 if (dpp_wait_rx(dut, ctrl, 1) < 0)
1050 result = "BootstrapResult,OK,AuthResult,Timeout";
1051 else
1052 result = "BootstrapResult,OK,AuthResult,Errorsent";
1053 }
1054
1055 if (strcasecmp(frametype, "AuthenticationConfirm") == 0) {
1056 if (dpp_wait_rx(dut, ctrl, 2) < 0)
1057 result = "BootstrapResult,OK,AuthResult,Timeout";
1058 else
1059 result = "BootstrapResult,OK,AuthResult,Errorsent";
1060 }
1061
1062 if (strcasecmp(frametype, "ConfigurationRequest") == 0) {
1063 if (get_wpa_cli_event(dut, ctrl, "DPP-CONF-FAILED",
1064 buf, sizeof(buf)) < 0)
1065 result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Timeout";
1066 else
1067 result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Errorsent";
1068 }
1069
1070 send_resp(dut, conn, SIGMA_COMPLETE, result);
1071 goto out;
1072 }
1073
Jouni Malinen772299f2017-11-06 00:36:26 +02001074 if (frametype && strcasecmp(frametype, "PKEXExchangeRequest") == 0) {
1075 if (dpp_wait_tx_status(dut, ctrl, 7) < 0)
1076 result = "BootstrapResult,Timeout";
1077 else
1078 result = "BootstrapResult,Errorsent";
1079 send_resp(dut, conn, SIGMA_COMPLETE, result);
1080 goto out;
1081 }
1082
1083 if (frametype && strcasecmp(frametype, "PKEXExchangeResponse") == 0) {
1084 if (dpp_wait_tx_status(dut, ctrl, 8) < 0)
1085 result = "BootstrapResult,Timeout";
1086 else
1087 result = "BootstrapResult,Errorsent";
1088 send_resp(dut, conn, SIGMA_COMPLETE, result);
1089 goto out;
1090 }
1091
1092 if (frametype && strcasecmp(frametype, "PKEXCRRequest") == 0) {
1093 if (dpp_wait_tx_status(dut, ctrl, 9) < 0)
1094 result = "BootstrapResult,Timeout";
1095 else
1096 result = "BootstrapResult,Errorsent";
1097 send_resp(dut, conn, SIGMA_COMPLETE, result);
1098 goto out;
1099 }
1100
1101 if (frametype && strcasecmp(frametype, "PKEXCRResponse") == 0) {
1102 if (dpp_wait_tx_status(dut, ctrl, 10) < 0)
1103 result = "BootstrapResult,Timeout";
1104 else
1105 result = "BootstrapResult,Errorsent";
1106 send_resp(dut, conn, SIGMA_COMPLETE, result);
1107 goto out;
1108 }
1109
1110 if (frametype && strcasecmp(frametype, "AuthenticationRequest") == 0) {
1111 if (dpp_wait_tx_status(dut, ctrl, 0) < 0)
1112 result = "BootstrapResult,OK,AuthResult,Timeout";
1113 else
1114 result = "BootstrapResult,OK,AuthResult,Errorsent";
1115 send_resp(dut, conn, SIGMA_COMPLETE, result);
1116 goto out;
1117 }
1118
1119 if (frametype && strcasecmp(frametype, "AuthenticationResponse") == 0) {
1120 if (dpp_wait_tx_status(dut, ctrl, 1) < 0)
1121 result = "BootstrapResult,OK,AuthResult,Timeout";
1122 else
1123 result = "BootstrapResult,OK,AuthResult,Errorsent";
1124 send_resp(dut, conn, SIGMA_COMPLETE, result);
1125 goto out;
1126 }
1127
Jouni Malinend1e22f72017-12-05 21:12:17 +02001128 if (check_mutual) {
1129 res = get_wpa_cli_event(dut, ctrl, "DPP-AUTH-DIRECTION",
1130 buf, sizeof(buf));
1131 if (res < 0) {
1132 send_resp(dut, conn, SIGMA_COMPLETE,
1133 "BootstrapResult,OK,AuthResult,Timeout");
1134 goto out;
1135 }
1136 sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP auth direction: %s",
1137 buf);
1138 if (strstr(buf, "mutual=1") == NULL) {
1139 send_resp(dut, conn, SIGMA_ERROR,
1140 "errorCode,Peer did not use mutual authentication");
1141 goto out;
1142 }
1143 }
1144
Jouni Malinen772299f2017-11-06 00:36:26 +02001145 if (frametype && strcasecmp(frametype, "AuthenticationConfirm") == 0) {
1146 if (dpp_wait_tx_status(dut, ctrl, 2) < 0)
1147 result = "BootstrapResult,OK,AuthResult,Timeout";
1148 else
1149 result = "BootstrapResult,OK,AuthResult,Errorsent";
1150 send_resp(dut, conn, SIGMA_COMPLETE, result);
1151 goto out;
1152 }
1153
Jouni Malinend86e5822017-08-29 03:55:32 +03001154 res = get_wpa_cli_events(dut, ctrl, auth_events, buf, sizeof(buf));
1155 if (res < 0) {
1156 send_resp(dut, conn, SIGMA_COMPLETE,
1157 "BootstrapResult,OK,AuthResult,Timeout");
1158 goto out;
1159 }
1160 sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP auth result: %s", buf);
1161
Jouni Malinen2e9c8a42017-11-19 12:06:18 +02001162 if (strstr(buf, "DPP-RESPONSE-PENDING")) {
1163 /* Wait for the actual result after the peer has scanned the
1164 * QR Code. */
1165 res = get_wpa_cli_events(dut, ctrl, auth_events,
1166 buf, sizeof(buf));
1167 if (res < 0) {
1168 send_resp(dut, conn, SIGMA_COMPLETE,
1169 "BootstrapResult,OK,AuthResult,Timeout");
1170 goto out;
1171 }
1172 }
1173
Jouni Malinend86e5822017-08-29 03:55:32 +03001174 if (strstr(buf, "DPP-NOT-COMPATIBLE")) {
1175 send_resp(dut, conn, SIGMA_COMPLETE,
1176 "BootstrapResult,OK,AuthResult,ROLES_NOT_COMPATIBLE");
1177 goto out;
1178 }
1179
1180 if (!strstr(buf, "DPP-AUTH-SUCCESS")) {
1181 send_resp(dut, conn, SIGMA_COMPLETE,
1182 "BootstrapResult,OK,AuthResult,FAILED");
1183 goto out;
1184 }
1185
Jouni Malinen772299f2017-11-06 00:36:26 +02001186 if (frametype && strcasecmp(frametype, "ConfigurationRequest") == 0) {
1187 res = get_wpa_cli_event(dut, ctrl, "GAS-QUERY-DONE",
1188 buf, sizeof(buf));
1189 if (res < 0)
1190 result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Timeout";
1191 else
1192 result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Errorsent";
1193 send_resp(dut, conn, SIGMA_COMPLETE, result);
1194 goto out;
1195 }
1196
1197 if (frametype && strcasecmp(frametype, "ConfigurationResponse") == 0) {
1198 res = get_wpa_cli_event(dut, ctrl, "DPP-CONF-SENT",
1199 buf, sizeof(buf));
1200 if (res < 0)
1201 result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Timeout";
1202 else
1203 result = "BootstrapResult,OK,AuthResult,OK,ConfResult,Errorsent";
1204 send_resp(dut, conn, SIGMA_COMPLETE, result);
1205 goto out;
1206 }
1207
Jouni Malinend86e5822017-08-29 03:55:32 +03001208 res = get_wpa_cli_events(dut, ctrl, conf_events, buf, sizeof(buf));
1209 if (res < 0) {
1210 send_resp(dut, conn, SIGMA_COMPLETE,
1211 "BootstrapResult,OK,AuthResult,OK,ConfResult,Timeout");
1212 goto out;
1213 }
1214 sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP conf result: %s", buf);
1215
1216 if (!strstr(buf, "DPP-CONF-SENT") &&
1217 !strstr(buf, "DPP-CONF-RECEIVED")) {
1218 send_resp(dut, conn, SIGMA_COMPLETE,
1219 "BootstrapResult,OK,AuthResult,OK,ConfResult,FAILED");
1220 goto out;
1221 }
1222
1223 if (sigma_dut_is_ap(dut) &&
1224 strcasecmp(prov_role, "Enrollee") == 0) {
Jouni Malinen174db642017-11-27 20:16:29 +02001225 update_ap:
Jouni Malinend86e5822017-08-29 03:55:32 +03001226 res = dpp_hostapd_conf_update(dut, conn, ifname, ctrl);
1227 if (res == 0)
1228 goto out;
1229 if (res < 0) {
1230 send_resp(dut, conn, SIGMA_ERROR, NULL);
1231 goto out;
1232 }
1233 }
1234
1235 if (strcasecmp(wait_conn, "Yes") == 0 &&
1236 !sigma_dut_is_ap(dut) &&
1237 strcasecmp(prov_role, "Enrollee") == 0) {
Jouni Malinenfbb268d2017-11-17 18:53:49 +02001238 wait_connect:
Jouni Malinen53558e02017-11-06 12:58:28 +02001239 if (frametype && strcasecmp(frametype,
1240 "PeerDiscoveryRequest") == 0) {
1241 if (dpp_wait_tx_status(dut, ctrl, 5) < 0)
1242 result = "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Timeout";
1243 else
1244 result = "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Errorsent";
1245 send_resp(dut, conn, SIGMA_COMPLETE, result);
1246 goto out;
1247 }
1248
Jouni Malinend86e5822017-08-29 03:55:32 +03001249 res = get_wpa_cli_events(dut, ctrl, conn_events,
1250 buf, sizeof(buf));
1251 if (res < 0) {
1252 send_resp(dut, conn, SIGMA_COMPLETE,
1253 "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Timeout,NetworkConnectResult,Timeout");
1254 goto out;
1255 }
1256 sigma_dut_print(dut, DUT_MSG_DEBUG, "DPP connect result: %s",
1257 buf);
1258
1259 if (strstr(buf, "PMKSA-CACHE-ADDED")) {
1260 res = get_wpa_cli_events(dut, ctrl, conn_events,
1261 buf, sizeof(buf));
1262 if (res < 0) {
1263 send_resp(dut, conn, SIGMA_COMPLETE,
1264 "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,OK,NetworkConnectResult,Timeout");
1265 goto out;
1266 }
1267 sigma_dut_print(dut, DUT_MSG_DEBUG,
1268 "DPP connect result: %s", buf);
1269 if (strstr(buf, "CTRL-EVENT-CONNECTED"))
1270 send_resp(dut, conn, SIGMA_COMPLETE,
1271 "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,OK,NetworkConnectResult,OK");
1272 else
1273 send_resp(dut, conn, SIGMA_COMPLETE,
1274 "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,OK,NetworkConnectResult,Timeout");
1275 goto out;
1276 }
1277
1278 send_resp(dut, conn, SIGMA_COMPLETE,
1279 "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkConnectResult,OK");
1280 goto out;
1281 }
1282
Jouni Malinen53558e02017-11-06 12:58:28 +02001283 if (strcasecmp(wait_conn, "Yes") == 0 &&
1284 frametype && strcasecmp(frametype, "PeerDiscoveryResponse") == 0) {
1285 if (dpp_wait_tx_status(dut, ctrl, 6) < 0)
1286 result = "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Timeout";
1287 else
1288 result = "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,Errorsent";
1289 send_resp(dut, conn, SIGMA_COMPLETE, result);
1290 goto out;
1291 }
1292
Jouni Malinend86e5822017-08-29 03:55:32 +03001293 send_resp(dut, conn, SIGMA_COMPLETE,
1294 "BootstrapResult,OK,AuthResult,OK,ConfResult,OK");
1295out:
1296 wpa_ctrl_detach(ctrl);
1297 wpa_ctrl_close(ctrl);
1298 dut->default_timeout = old_timeout;
1299 return 0;
1300}
1301
1302
1303int dpp_dev_exec_action(struct sigma_dut *dut, struct sigma_conn *conn,
1304 struct sigma_cmd *cmd)
1305{
1306 const char *type = get_param(cmd, "DPPActionType");
1307 const char *bs = get_param(cmd, "DPPBS");
1308
1309 if (!bs) {
1310 send_resp(dut, conn, SIGMA_ERROR,
1311 "errorCode,Missing DPPBS");
1312 return 0;
1313 }
1314
1315 if (!type) {
1316 send_resp(dut, conn, SIGMA_ERROR,
1317 "errorCode,Missing DPPActionType");
1318 return 0;
1319 }
1320
1321 if (strcasecmp(type, "GetLocalBootstrap") == 0)
1322 return dpp_get_local_bootstrap(dut, conn, cmd);
1323 if (strcasecmp(type, "SetPeerBootstrap") == 0)
1324 return dpp_set_peer_bootstrap(dut, conn, cmd);
1325 if (strcasecmp(type, "ManualDPP") == 0)
1326 return dpp_manual_dpp(dut, conn, cmd);
1327 if (strcasecmp(type, "AutomaticDPP") == 0)
1328 return dpp_automatic_dpp(dut, conn, cmd);
1329
1330 send_resp(dut, conn, SIGMA_ERROR,
1331 "errorCode,Unsupported DPPActionType");
1332 return 0;
1333}