blob: 1a3a815cbef9d18ab713a7c328d5507d1512dc6f [file] [log] [blame]
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001/*
2 * hostapd / DPP integration
3 * Copyright (c) 2017, Qualcomm Atheros, Inc.
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004 * Copyright (c) 2018-2019, The Linux Foundation
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005 *
6 * This software may be distributed under the terms of the BSD license.
7 * See README for more details.
8 */
9
10#include "utils/includes.h"
11
12#include "utils/common.h"
13#include "utils/eloop.h"
14#include "common/dpp.h"
15#include "common/gas.h"
16#include "common/wpa_ctrl.h"
17#include "hostapd.h"
18#include "ap_drv_ops.h"
19#include "gas_query_ap.h"
Hai Shalom81f62d82019-07-22 12:10:00 -070020#include "gas_serv.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070021#include "wpa_auth.h"
22#include "dpp_hostapd.h"
23
24
Roshan Pius3a1667e2018-07-03 15:17:14 -070025static void hostapd_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070026static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator);
Roshan Pius3a1667e2018-07-03 15:17:14 -070027static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx);
28static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070029
30static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
31
32
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070033/**
34 * hostapd_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
35 * @hapd: Pointer to hostapd_data
36 * @cmd: DPP URI read from a QR Code
37 * Returns: Identifier of the stored info or -1 on failure
38 */
39int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd)
40{
41 struct dpp_bootstrap_info *bi;
42 struct dpp_authentication *auth = hapd->dpp_auth;
43
Hai Shalom021b0b52019-04-10 11:17:58 -070044 bi = dpp_add_qr_code(hapd->iface->interfaces->dpp, cmd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070045 if (!bi)
46 return -1;
47
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070048 if (auth && auth->response_pending &&
49 dpp_notify_new_qr_code(auth, bi) == 1) {
50 wpa_printf(MSG_DEBUG,
51 "DPP: Sending out pending authentication response");
Roshan Pius3a1667e2018-07-03 15:17:14 -070052 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
53 " freq=%u type=%d",
54 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
55 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070056 hostapd_drv_send_action(hapd, auth->curr_freq, 0,
57 auth->peer_mac_addr,
58 wpabuf_head(hapd->dpp_auth->resp_msg),
59 wpabuf_len(hapd->dpp_auth->resp_msg));
60 }
61
62 return bi->id;
63}
64
65
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -080066/**
67 * hostapd_dpp_nfc_uri - Parse and add DPP bootstrapping info from NFC Tag (URI)
68 * @hapd: Pointer to hostapd_data
69 * @cmd: DPP URI read from a NFC Tag (URI NDEF message)
70 * Returns: Identifier of the stored info or -1 on failure
71 */
72int hostapd_dpp_nfc_uri(struct hostapd_data *hapd, const char *cmd)
73{
74 struct dpp_bootstrap_info *bi;
75
76 bi = dpp_add_nfc_uri(hapd->iface->interfaces->dpp, cmd);
77 if (!bi)
78 return -1;
79
80 return bi->id;
81}
82
83
Roshan Pius3a1667e2018-07-03 15:17:14 -070084static void hostapd_dpp_auth_resp_retry_timeout(void *eloop_ctx,
85 void *timeout_ctx)
86{
87 struct hostapd_data *hapd = eloop_ctx;
88 struct dpp_authentication *auth = hapd->dpp_auth;
89
90 if (!auth || !auth->resp_msg)
91 return;
92
93 wpa_printf(MSG_DEBUG,
94 "DPP: Retry Authentication Response after timeout");
95 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
96 " freq=%u type=%d",
97 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
98 DPP_PA_AUTHENTICATION_RESP);
99 hostapd_drv_send_action(hapd, auth->curr_freq, 500, auth->peer_mac_addr,
100 wpabuf_head(auth->resp_msg),
101 wpabuf_len(auth->resp_msg));
102}
103
104
105static void hostapd_dpp_auth_resp_retry(struct hostapd_data *hapd)
106{
107 struct dpp_authentication *auth = hapd->dpp_auth;
108 unsigned int wait_time, max_tries;
109
110 if (!auth || !auth->resp_msg)
111 return;
112
113 if (hapd->dpp_resp_max_tries)
114 max_tries = hapd->dpp_resp_max_tries;
115 else
116 max_tries = 5;
117 auth->auth_resp_tries++;
118 if (auth->auth_resp_tries >= max_tries) {
119 wpa_printf(MSG_INFO,
120 "DPP: No confirm received from initiator - stopping exchange");
121 hostapd_drv_send_action_cancel_wait(hapd);
122 dpp_auth_deinit(hapd->dpp_auth);
123 hapd->dpp_auth = NULL;
124 return;
125 }
126
127 if (hapd->dpp_resp_retry_time)
128 wait_time = hapd->dpp_resp_retry_time;
129 else
130 wait_time = 1000;
131 wpa_printf(MSG_DEBUG,
132 "DPP: Schedule retransmission of Authentication Response frame in %u ms",
133 wait_time);
134 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
135 eloop_register_timeout(wait_time / 1000,
136 (wait_time % 1000) * 1000,
137 hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
138}
139
140
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700141void hostapd_dpp_tx_status(struct hostapd_data *hapd, const u8 *dst,
142 const u8 *data, size_t data_len, int ok)
143{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700144 struct dpp_authentication *auth = hapd->dpp_auth;
145
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700146 wpa_printf(MSG_DEBUG, "DPP: TX status: dst=" MACSTR " ok=%d",
147 MAC2STR(dst), ok);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700148 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
149 " result=%s", MAC2STR(dst), ok ? "SUCCESS" : "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700150
151 if (!hapd->dpp_auth) {
152 wpa_printf(MSG_DEBUG,
153 "DPP: Ignore TX status since there is no ongoing authentication exchange");
154 return;
155 }
156
Hai Shalom021b0b52019-04-10 11:17:58 -0700157#ifdef CONFIG_DPP2
158 if (auth->connect_on_tx_status) {
159 wpa_printf(MSG_DEBUG,
160 "DPP: Complete exchange on configuration result");
161 dpp_auth_deinit(hapd->dpp_auth);
162 hapd->dpp_auth = NULL;
163 return;
164 }
165#endif /* CONFIG_DPP2 */
166
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700167 if (hapd->dpp_auth->remove_on_tx_status) {
168 wpa_printf(MSG_DEBUG,
169 "DPP: Terminate authentication exchange due to an earlier error");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700170 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
171 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
172 hapd, NULL);
173 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
174 NULL);
175 hostapd_drv_send_action_cancel_wait(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700176 dpp_auth_deinit(hapd->dpp_auth);
177 hapd->dpp_auth = NULL;
178 return;
179 }
180
181 if (hapd->dpp_auth_ok_on_ack)
182 hostapd_dpp_auth_success(hapd, 1);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700183
184 if (!is_broadcast_ether_addr(dst) && !ok) {
185 wpa_printf(MSG_DEBUG,
186 "DPP: Unicast DPP Action frame was not ACKed");
187 if (auth->waiting_auth_resp) {
188 /* In case of DPP Authentication Request frame, move to
189 * the next channel immediately. */
190 hostapd_drv_send_action_cancel_wait(hapd);
191 hostapd_dpp_auth_init_next(hapd);
192 return;
193 }
194 if (auth->waiting_auth_conf) {
195 hostapd_dpp_auth_resp_retry(hapd);
196 return;
197 }
198 }
199
200 if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp && ok) {
201 /* Allow timeout handling to stop iteration if no response is
202 * received from a peer that has ACKed a request. */
203 auth->auth_req_ack = 1;
204 }
205
206 if (!hapd->dpp_auth_ok_on_ack && hapd->dpp_auth->neg_freq > 0 &&
207 hapd->dpp_auth->curr_freq != hapd->dpp_auth->neg_freq) {
208 wpa_printf(MSG_DEBUG,
209 "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response",
210 hapd->dpp_auth->curr_freq,
211 hapd->dpp_auth->neg_freq);
212 hostapd_drv_send_action_cancel_wait(hapd);
213
214 if (hapd->dpp_auth->neg_freq !=
215 (unsigned int) hapd->iface->freq && hapd->iface->freq > 0) {
216 /* TODO: Listen operation on non-operating channel */
217 wpa_printf(MSG_INFO,
218 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
219 hapd->dpp_auth->neg_freq, hapd->iface->freq);
220 }
221 }
222
223 if (hapd->dpp_auth_ok_on_ack)
224 hapd->dpp_auth_ok_on_ack = 0;
225}
226
227
228static void hostapd_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx)
229{
230 struct hostapd_data *hapd = eloop_ctx;
231 struct dpp_authentication *auth = hapd->dpp_auth;
232 unsigned int freq;
233 struct os_reltime now, diff;
234 unsigned int wait_time, diff_ms;
235
236 if (!auth || !auth->waiting_auth_resp)
237 return;
238
239 wait_time = hapd->dpp_resp_wait_time ?
240 hapd->dpp_resp_wait_time : 2000;
241 os_get_reltime(&now);
242 os_reltime_sub(&now, &hapd->dpp_last_init, &diff);
243 diff_ms = diff.sec * 1000 + diff.usec / 1000;
244 wpa_printf(MSG_DEBUG,
245 "DPP: Reply wait timeout - wait_time=%u diff_ms=%u",
246 wait_time, diff_ms);
247
248 if (auth->auth_req_ack && diff_ms >= wait_time) {
249 /* Peer ACK'ed Authentication Request frame, but did not reply
250 * with Authentication Response frame within two seconds. */
251 wpa_printf(MSG_INFO,
252 "DPP: No response received from responder - stopping initiation attempt");
253 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
254 hostapd_drv_send_action_cancel_wait(hapd);
255 hostapd_dpp_listen_stop(hapd);
256 dpp_auth_deinit(auth);
257 hapd->dpp_auth = NULL;
258 return;
259 }
260
261 if (diff_ms >= wait_time) {
262 /* Authentication Request frame was not ACK'ed and no reply
263 * was receiving within two seconds. */
264 wpa_printf(MSG_DEBUG,
265 "DPP: Continue Initiator channel iteration");
266 hostapd_drv_send_action_cancel_wait(hapd);
267 hostapd_dpp_listen_stop(hapd);
268 hostapd_dpp_auth_init_next(hapd);
269 return;
270 }
271
272 /* Driver did not support 2000 ms long wait_time with TX command, so
273 * schedule listen operation to continue waiting for the response.
274 *
275 * DPP listen operations continue until stopped, so simply schedule a
276 * new call to this function at the point when the two second reply
277 * wait has expired. */
278 wait_time -= diff_ms;
279
280 freq = auth->curr_freq;
281 if (auth->neg_freq > 0)
282 freq = auth->neg_freq;
283 wpa_printf(MSG_DEBUG,
284 "DPP: Continue reply wait on channel %u MHz for %u ms",
285 freq, wait_time);
286 hapd->dpp_in_response_listen = 1;
287
288 if (freq != (unsigned int) hapd->iface->freq && hapd->iface->freq > 0) {
289 /* TODO: Listen operation on non-operating channel */
290 wpa_printf(MSG_INFO,
291 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
292 freq, hapd->iface->freq);
293 }
294
295 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
296 hostapd_dpp_reply_wait_timeout, hapd, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700297}
298
299
300static void hostapd_dpp_set_testing_options(struct hostapd_data *hapd,
301 struct dpp_authentication *auth)
302{
303#ifdef CONFIG_TESTING_OPTIONS
304 if (hapd->dpp_config_obj_override)
305 auth->config_obj_override =
306 os_strdup(hapd->dpp_config_obj_override);
307 if (hapd->dpp_discovery_override)
308 auth->discovery_override =
309 os_strdup(hapd->dpp_discovery_override);
310 if (hapd->dpp_groups_override)
311 auth->groups_override = os_strdup(hapd->dpp_groups_override);
312 auth->ignore_netaccesskey_mismatch =
313 hapd->dpp_ignore_netaccesskey_mismatch;
314#endif /* CONFIG_TESTING_OPTIONS */
315}
316
317
Roshan Pius3a1667e2018-07-03 15:17:14 -0700318static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
319{
320 struct hostapd_data *hapd = eloop_ctx;
321
322 if (!hapd->dpp_auth)
323 return;
324 wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout");
325 hostapd_dpp_auth_init_next(hapd);
326}
327
328
329static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd)
330{
331 struct dpp_authentication *auth = hapd->dpp_auth;
332 const u8 *dst;
333 unsigned int wait_time, max_wait_time, freq, max_tries, used;
334 struct os_reltime now, diff;
335
336 if (!auth)
337 return -1;
338
339 if (auth->freq_idx == 0)
340 os_get_reltime(&hapd->dpp_init_iter_start);
341
342 if (auth->freq_idx >= auth->num_freq) {
343 auth->num_freq_iters++;
344 if (hapd->dpp_init_max_tries)
345 max_tries = hapd->dpp_init_max_tries;
346 else
347 max_tries = 5;
348 if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) {
349 wpa_printf(MSG_INFO,
350 "DPP: No response received from responder - stopping initiation attempt");
351 wpa_msg(hapd->msg_ctx, MSG_INFO,
352 DPP_EVENT_AUTH_INIT_FAILED);
353 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
354 hapd, NULL);
355 hostapd_drv_send_action_cancel_wait(hapd);
356 dpp_auth_deinit(hapd->dpp_auth);
357 hapd->dpp_auth = NULL;
358 return -1;
359 }
360 auth->freq_idx = 0;
361 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
362 if (hapd->dpp_init_retry_time)
363 wait_time = hapd->dpp_init_retry_time;
364 else
365 wait_time = 10000;
366 os_get_reltime(&now);
367 os_reltime_sub(&now, &hapd->dpp_init_iter_start, &diff);
368 used = diff.sec * 1000 + diff.usec / 1000;
369 if (used > wait_time)
370 wait_time = 0;
371 else
372 wait_time -= used;
373 wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms",
374 wait_time);
375 eloop_register_timeout(wait_time / 1000,
376 (wait_time % 1000) * 1000,
377 hostapd_dpp_init_timeout, hapd,
378 NULL);
379 return 0;
380 }
381 freq = auth->freq[auth->freq_idx++];
382 auth->curr_freq = freq;
383
384 if (is_zero_ether_addr(auth->peer_bi->mac_addr))
385 dst = broadcast;
386 else
387 dst = auth->peer_bi->mac_addr;
388 hapd->dpp_auth_ok_on_ack = 0;
389 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
390 wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
391 max_wait_time = hapd->dpp_resp_wait_time ?
392 hapd->dpp_resp_wait_time : 2000;
393 if (wait_time > max_wait_time)
394 wait_time = max_wait_time;
395 wait_time += 10; /* give the driver some extra time to complete */
396 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
397 hostapd_dpp_reply_wait_timeout, hapd, NULL);
398 wait_time -= 10;
399 if (auth->neg_freq > 0 && freq != auth->neg_freq) {
400 wpa_printf(MSG_DEBUG,
401 "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response",
402 freq, auth->neg_freq);
403 }
404 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
405 " freq=%u type=%d",
406 MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ);
407 auth->auth_req_ack = 0;
408 os_get_reltime(&hapd->dpp_last_init);
409 return hostapd_drv_send_action(hapd, freq, wait_time,
410 dst,
411 wpabuf_head(hapd->dpp_auth->req_msg),
412 wpabuf_len(hapd->dpp_auth->req_msg));
413}
414
415
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700416int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
417{
418 const char *pos;
419 struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700420 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
421 unsigned int neg_freq = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700422
423 pos = os_strstr(cmd, " peer=");
424 if (!pos)
425 return -1;
426 pos += 6;
Hai Shalom021b0b52019-04-10 11:17:58 -0700427 peer_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700428 if (!peer_bi) {
429 wpa_printf(MSG_INFO,
430 "DPP: Could not find bootstrapping info for the identified peer");
431 return -1;
432 }
433
434 pos = os_strstr(cmd, " own=");
435 if (pos) {
436 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -0700437 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp,
438 atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700439 if (!own_bi) {
440 wpa_printf(MSG_INFO,
441 "DPP: Could not find bootstrapping info for the identified local entry");
442 return -1;
443 }
444
445 if (peer_bi->curve != own_bi->curve) {
446 wpa_printf(MSG_INFO,
447 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
448 peer_bi->curve->name, own_bi->curve->name);
449 return -1;
450 }
451 }
452
453 pos = os_strstr(cmd, " role=");
454 if (pos) {
455 pos += 6;
456 if (os_strncmp(pos, "configurator", 12) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700457 allowed_roles = DPP_CAPAB_CONFIGURATOR;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700458 else if (os_strncmp(pos, "enrollee", 8) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700459 allowed_roles = DPP_CAPAB_ENROLLEE;
460 else if (os_strncmp(pos, "either", 6) == 0)
461 allowed_roles = DPP_CAPAB_CONFIGURATOR |
462 DPP_CAPAB_ENROLLEE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700463 else
464 goto fail;
465 }
466
Roshan Pius3a1667e2018-07-03 15:17:14 -0700467 pos = os_strstr(cmd, " neg_freq=");
468 if (pos)
469 neg_freq = atoi(pos + 10);
470
471 if (hapd->dpp_auth) {
472 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
473 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
474 hapd, NULL);
475 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
476 NULL);
477 hostapd_drv_send_action_cancel_wait(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700478 dpp_auth_deinit(hapd->dpp_auth);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700479 }
480
481 hapd->dpp_auth = dpp_auth_init(hapd->msg_ctx, peer_bi, own_bi,
482 allowed_roles, neg_freq,
483 hapd->iface->hw_features,
484 hapd->iface->num_hw_features);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700485 if (!hapd->dpp_auth)
486 goto fail;
487 hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
Hai Shalom021b0b52019-04-10 11:17:58 -0700488 if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx,
489 hapd->dpp_auth, cmd) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -0800490 dpp_auth_deinit(hapd->dpp_auth);
491 hapd->dpp_auth = NULL;
492 goto fail;
493 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700494
Roshan Pius3a1667e2018-07-03 15:17:14 -0700495 hapd->dpp_auth->neg_freq = neg_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700496
Roshan Pius3a1667e2018-07-03 15:17:14 -0700497 if (!is_zero_ether_addr(peer_bi->mac_addr))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700498 os_memcpy(hapd->dpp_auth->peer_mac_addr, peer_bi->mac_addr,
499 ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700500
Roshan Pius3a1667e2018-07-03 15:17:14 -0700501 return hostapd_dpp_auth_init_next(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700502fail:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700503 return -1;
504}
505
506
Roshan Pius3a1667e2018-07-03 15:17:14 -0700507int hostapd_dpp_listen(struct hostapd_data *hapd, const char *cmd)
508{
509 int freq;
510
511 freq = atoi(cmd);
512 if (freq <= 0)
513 return -1;
514
515 if (os_strstr(cmd, " role=configurator"))
516 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
517 else if (os_strstr(cmd, " role=enrollee"))
518 hapd->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
519 else
520 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
521 DPP_CAPAB_ENROLLEE;
522 hapd->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
523
524 if (freq != hapd->iface->freq && hapd->iface->freq > 0) {
525 /* TODO: Listen operation on non-operating channel */
526 wpa_printf(MSG_INFO,
527 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
528 freq, hapd->iface->freq);
529 return -1;
530 }
531
532 return 0;
533}
534
535
536void hostapd_dpp_listen_stop(struct hostapd_data *hapd)
537{
538 /* TODO: Stop listen operation on non-operating channel */
539}
540
541
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700542static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src,
543 const u8 *hdr, const u8 *buf, size_t len,
544 unsigned int freq)
545{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700546 const u8 *r_bootstrap, *i_bootstrap;
547 u16 r_bootstrap_len, i_bootstrap_len;
Hai Shalom021b0b52019-04-10 11:17:58 -0700548 struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
549
550 if (!hapd->iface->interfaces->dpp)
551 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700552
553 wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
554 MAC2STR(src));
555
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700556 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
557 &r_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700558 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
559 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
560 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700561 return;
562 }
563 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
564 r_bootstrap, r_bootstrap_len);
565
566 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
567 &i_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700568 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
569 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
570 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700571 return;
572 }
573 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
574 i_bootstrap, i_bootstrap_len);
575
576 /* Try to find own and peer bootstrapping key matches based on the
577 * received hash values */
Hai Shalom021b0b52019-04-10 11:17:58 -0700578 dpp_bootstrap_find_pair(hapd->iface->interfaces->dpp, i_bootstrap,
579 r_bootstrap, &own_bi, &peer_bi);
Hai Shalom81f62d82019-07-22 12:10:00 -0700580#ifdef CONFIG_DPP2
581 if (!own_bi) {
582 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
583 src, hdr, buf, len, freq, i_bootstrap,
584 r_bootstrap) == 0)
585 return;
586 }
587#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700588 if (!own_bi) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700589 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
590 "No matching own bootstrapping key found - ignore message");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700591 return;
592 }
593
594 if (hapd->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700595 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
596 "Already in DPP authentication exchange - ignore new one");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700597 return;
598 }
599
600 hapd->dpp_auth_ok_on_ack = 0;
601 hapd->dpp_auth = dpp_auth_req_rx(hapd->msg_ctx, hapd->dpp_allowed_roles,
602 hapd->dpp_qr_mutual,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700603 peer_bi, own_bi, freq, hdr, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700604 if (!hapd->dpp_auth) {
605 wpa_printf(MSG_DEBUG, "DPP: No response generated");
606 return;
607 }
608 hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
Hai Shalom021b0b52019-04-10 11:17:58 -0700609 if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx,
610 hapd->dpp_auth,
611 hapd->dpp_configurator_params) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -0800612 dpp_auth_deinit(hapd->dpp_auth);
613 hapd->dpp_auth = NULL;
614 return;
615 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700616 os_memcpy(hapd->dpp_auth->peer_mac_addr, src, ETH_ALEN);
617
Roshan Pius3a1667e2018-07-03 15:17:14 -0700618 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
619 " freq=%u type=%d",
620 MAC2STR(src), hapd->dpp_auth->curr_freq,
621 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700622 hostapd_drv_send_action(hapd, hapd->dpp_auth->curr_freq, 0,
623 src, wpabuf_head(hapd->dpp_auth->resp_msg),
624 wpabuf_len(hapd->dpp_auth->resp_msg));
625}
626
627
Roshan Pius3a1667e2018-07-03 15:17:14 -0700628static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd,
Hai Shalomc3565922019-10-28 11:58:20 -0700629 struct dpp_authentication *auth,
630 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700631{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700632 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700633 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
Hai Shalomc3565922019-10-28 11:58:20 -0700634 dpp_akm_str(conf->akm));
635 if (conf->ssid_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700636 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
Hai Shalomc3565922019-10-28 11:58:20 -0700637 wpa_ssid_txt(conf->ssid, conf->ssid_len));
638 if (conf->connector) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700639 /* TODO: Save the Connector and consider using a command
640 * to fetch the value instead of sending an event with
641 * it. The Connector could end up being larger than what
642 * most clients are ready to receive as an event
643 * message. */
644 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
Hai Shalomc3565922019-10-28 11:58:20 -0700645 conf->connector);
646 } else if (conf->passphrase[0]) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700647 char hex[64 * 2 + 1];
648
649 wpa_snprintf_hex(hex, sizeof(hex),
Hai Shalomc3565922019-10-28 11:58:20 -0700650 (const u8 *) conf->passphrase,
651 os_strlen(conf->passphrase));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700652 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
653 hex);
Hai Shalomc3565922019-10-28 11:58:20 -0700654 } else if (conf->psk_set) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700655 char hex[PMK_LEN * 2 + 1];
656
Hai Shalomc3565922019-10-28 11:58:20 -0700657 wpa_snprintf_hex(hex, sizeof(hex), conf->psk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700658 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
659 hex);
660 }
Hai Shalomc3565922019-10-28 11:58:20 -0700661 if (conf->c_sign_key) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700662 char *hex;
663 size_t hexlen;
664
Hai Shalomc3565922019-10-28 11:58:20 -0700665 hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700666 hex = os_malloc(hexlen);
667 if (hex) {
668 wpa_snprintf_hex(hex, hexlen,
Hai Shalomc3565922019-10-28 11:58:20 -0700669 wpabuf_head(conf->c_sign_key),
670 wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700671 wpa_msg(hapd->msg_ctx, MSG_INFO,
672 DPP_EVENT_C_SIGN_KEY "%s", hex);
673 os_free(hex);
674 }
675 }
676 if (auth->net_access_key) {
677 char *hex;
678 size_t hexlen;
679
680 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
681 hex = os_malloc(hexlen);
682 if (hex) {
683 wpa_snprintf_hex(hex, hexlen,
684 wpabuf_head(auth->net_access_key),
685 wpabuf_len(auth->net_access_key));
686 if (auth->net_access_key_expiry)
687 wpa_msg(hapd->msg_ctx, MSG_INFO,
688 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
689 (unsigned long)
690 auth->net_access_key_expiry);
691 else
692 wpa_msg(hapd->msg_ctx, MSG_INFO,
693 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
694 os_free(hex);
695 }
696 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700697}
698
699
700static void hostapd_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
701 enum gas_query_ap_result result,
702 const struct wpabuf *adv_proto,
703 const struct wpabuf *resp, u16 status_code)
704{
705 struct hostapd_data *hapd = ctx;
706 const u8 *pos;
707 struct dpp_authentication *auth = hapd->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -0700708 enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700709
710 if (!auth || !auth->auth_success) {
711 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
712 return;
713 }
714 if (!resp || status_code != WLAN_STATUS_SUCCESS) {
715 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
716 goto fail;
717 }
718
719 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
720 adv_proto);
721 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
722 resp);
723
724 if (wpabuf_len(adv_proto) != 10 ||
725 !(pos = wpabuf_head(adv_proto)) ||
726 pos[0] != WLAN_EID_ADV_PROTO ||
727 pos[1] != 8 ||
728 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
729 pos[4] != 5 ||
730 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
731 pos[8] != 0x1a ||
732 pos[9] != 1) {
733 wpa_printf(MSG_DEBUG,
734 "DPP: Not a DPP Advertisement Protocol ID");
735 goto fail;
736 }
737
738 if (dpp_conf_resp_rx(auth, resp) < 0) {
739 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
740 goto fail;
741 }
742
Hai Shalomc3565922019-10-28 11:58:20 -0700743 hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]);
Hai Shalom021b0b52019-04-10 11:17:58 -0700744 status = DPP_STATUS_OK;
745#ifdef CONFIG_TESTING_OPTIONS
746 if (dpp_test == DPP_TEST_REJECT_CONFIG) {
747 wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object");
748 status = DPP_STATUS_CONFIG_REJECTED;
749 }
750#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700751fail:
Hai Shalom021b0b52019-04-10 11:17:58 -0700752 if (status != DPP_STATUS_OK)
753 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
754#ifdef CONFIG_DPP2
755 if (auth->peer_version >= 2 &&
756 auth->conf_resp_status == DPP_STATUS_OK) {
757 struct wpabuf *msg;
758
759 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
760 msg = dpp_build_conf_result(auth, status);
761 if (!msg)
762 goto fail2;
763
764 wpa_msg(hapd->msg_ctx, MSG_INFO,
765 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
766 MAC2STR(addr), auth->curr_freq,
767 DPP_PA_CONFIGURATION_RESULT);
768 hostapd_drv_send_action(hapd, auth->curr_freq, 0,
769 addr, wpabuf_head(msg),
770 wpabuf_len(msg));
771 wpabuf_free(msg);
772
773 /* This exchange will be terminated in the TX status handler */
774 auth->connect_on_tx_status = 1;
775 return;
776 }
777fail2:
778#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700779 dpp_auth_deinit(hapd->dpp_auth);
780 hapd->dpp_auth = NULL;
781}
782
783
784static void hostapd_dpp_start_gas_client(struct hostapd_data *hapd)
785{
786 struct dpp_authentication *auth = hapd->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -0700787 struct wpabuf *buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700788 int res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700789
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800790 buf = dpp_build_conf_req_helper(auth, hapd->conf->dpp_name,
791 DPP_NETROLE_AP,
Hai Shalomc3565922019-10-28 11:58:20 -0700792 hapd->conf->dpp_mud_url, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -0700793 if (!buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700794 wpa_printf(MSG_DEBUG,
795 "DPP: No configuration request data available");
796 return;
797 }
798
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700799 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
800 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
801
802 res = gas_query_ap_req(hapd->gas, auth->peer_mac_addr, auth->curr_freq,
803 buf, hostapd_dpp_gas_resp_cb, hapd);
804 if (res < 0) {
805 wpa_msg(hapd->msg_ctx, MSG_DEBUG,
806 "GAS: Failed to send Query Request");
807 wpabuf_free(buf);
808 } else {
809 wpa_printf(MSG_DEBUG,
810 "DPP: GAS query started with dialog token %u", res);
811 }
812}
813
814
815static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator)
816{
817 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
818 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d",
819 initiator);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700820#ifdef CONFIG_TESTING_OPTIONS
821 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
822 wpa_printf(MSG_INFO,
823 "DPP: TESTING - stop at Authentication Confirm");
824 if (hapd->dpp_auth->configurator) {
825 /* Prevent GAS response */
826 hapd->dpp_auth->auth_success = 0;
827 }
828 return;
829 }
830#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700831
832 if (!hapd->dpp_auth->configurator)
833 hostapd_dpp_start_gas_client(hapd);
834}
835
836
837static void hostapd_dpp_rx_auth_resp(struct hostapd_data *hapd, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700838 const u8 *hdr, const u8 *buf, size_t len,
839 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700840{
841 struct dpp_authentication *auth = hapd->dpp_auth;
842 struct wpabuf *msg;
843
844 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR,
845 MAC2STR(src));
846
847 if (!auth) {
848 wpa_printf(MSG_DEBUG,
849 "DPP: No DPP Authentication in progress - drop");
850 return;
851 }
852
853 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
854 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
855 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
856 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
857 return;
858 }
859
Roshan Pius3a1667e2018-07-03 15:17:14 -0700860 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
861
862 if (auth->curr_freq != freq && auth->neg_freq == freq) {
863 wpa_printf(MSG_DEBUG,
864 "DPP: Responder accepted request for different negotiation channel");
865 auth->curr_freq = freq;
866 }
867
868 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700869 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
870 if (!msg) {
871 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
872 wpa_printf(MSG_DEBUG, "DPP: Wait for full response");
873 return;
874 }
875 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
876 return;
877 }
878 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
879
Roshan Pius3a1667e2018-07-03 15:17:14 -0700880 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
881 " freq=%u type=%d", MAC2STR(src), auth->curr_freq,
882 DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700883 hostapd_drv_send_action(hapd, auth->curr_freq, 0, src,
884 wpabuf_head(msg), wpabuf_len(msg));
885 wpabuf_free(msg);
886 hapd->dpp_auth_ok_on_ack = 1;
887}
888
889
890static void hostapd_dpp_rx_auth_conf(struct hostapd_data *hapd, const u8 *src,
891 const u8 *hdr, const u8 *buf, size_t len)
892{
893 struct dpp_authentication *auth = hapd->dpp_auth;
894
895 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
896 MAC2STR(src));
897
898 if (!auth) {
899 wpa_printf(MSG_DEBUG,
900 "DPP: No DPP Authentication in progress - drop");
901 return;
902 }
903
904 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
905 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
906 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
907 return;
908 }
909
910 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
911 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
912 return;
913 }
914
915 hostapd_dpp_auth_success(hapd, 0);
916}
917
918
Hai Shalom021b0b52019-04-10 11:17:58 -0700919#ifdef CONFIG_DPP2
920
921static void hostapd_dpp_config_result_wait_timeout(void *eloop_ctx,
922 void *timeout_ctx)
923{
924 struct hostapd_data *hapd = eloop_ctx;
925 struct dpp_authentication *auth = hapd->dpp_auth;
926
927 if (!auth || !auth->waiting_conf_result)
928 return;
929
930 wpa_printf(MSG_DEBUG,
931 "DPP: Timeout while waiting for Configuration Result");
932 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
933 dpp_auth_deinit(auth);
934 hapd->dpp_auth = NULL;
935}
936
937
Hai Shalomc3565922019-10-28 11:58:20 -0700938static void hostapd_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
939 void *timeout_ctx)
940{
941 struct hostapd_data *hapd = eloop_ctx;
942 struct dpp_authentication *auth = hapd->dpp_auth;
943
944 if (!auth || !auth->waiting_conf_result)
945 return;
946
947 wpa_printf(MSG_DEBUG,
948 "DPP: Timeout while waiting for Connection Status Result");
949 wpa_msg(hapd->msg_ctx, MSG_INFO,
950 DPP_EVENT_CONN_STATUS_RESULT "timeout");
951 dpp_auth_deinit(auth);
952 hapd->dpp_auth = NULL;
953}
954
955
Hai Shalom021b0b52019-04-10 11:17:58 -0700956static void hostapd_dpp_rx_conf_result(struct hostapd_data *hapd, const u8 *src,
957 const u8 *hdr, const u8 *buf, size_t len)
958{
959 struct dpp_authentication *auth = hapd->dpp_auth;
960 enum dpp_status_error status;
961
962 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
963 MAC2STR(src));
964
965 if (!auth || !auth->waiting_conf_result) {
966 wpa_printf(MSG_DEBUG,
967 "DPP: No DPP Configuration waiting for result - drop");
968 return;
969 }
970
971 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
972 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
973 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
974 return;
975 }
976
977 status = dpp_conf_result_rx(auth, hdr, buf, len);
978
Hai Shalomc3565922019-10-28 11:58:20 -0700979 if (status == DPP_STATUS_OK && auth->send_conn_status) {
980 wpa_msg(hapd->msg_ctx, MSG_INFO,
981 DPP_EVENT_CONF_SENT "wait_conn_status=1");
982 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
983 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
984 hapd, NULL);
985 eloop_cancel_timeout(
986 hostapd_dpp_conn_status_result_wait_timeout,
987 hapd, NULL);
988 eloop_register_timeout(
989 16, 0, hostapd_dpp_conn_status_result_wait_timeout,
990 hapd, NULL);
991 return;
992 }
Hai Shalom021b0b52019-04-10 11:17:58 -0700993 hostapd_drv_send_action_cancel_wait(hapd);
994 hostapd_dpp_listen_stop(hapd);
995 if (status == DPP_STATUS_OK)
996 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
997 else
998 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
999 dpp_auth_deinit(auth);
1000 hapd->dpp_auth = NULL;
1001 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
1002 NULL);
1003}
1004
Hai Shalomc3565922019-10-28 11:58:20 -07001005
1006static void hostapd_dpp_rx_conn_status_result(struct hostapd_data *hapd,
1007 const u8 *src, const u8 *hdr,
1008 const u8 *buf, size_t len)
1009{
1010 struct dpp_authentication *auth = hapd->dpp_auth;
1011 enum dpp_status_error status;
1012 u8 ssid[SSID_MAX_LEN];
1013 size_t ssid_len = 0;
1014 char *channel_list = NULL;
1015
1016 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
1017
1018 if (!auth || !auth->waiting_conn_status_result) {
1019 wpa_printf(MSG_DEBUG,
1020 "DPP: No DPP Configuration waiting for connection status result - drop");
1021 return;
1022 }
1023
1024 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
1025 ssid, &ssid_len, &channel_list);
1026 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
1027 "result=%d ssid=%s channel_list=%s",
1028 status, wpa_ssid_txt(ssid, ssid_len),
1029 channel_list ? channel_list : "N/A");
1030 os_free(channel_list);
1031 hostapd_drv_send_action_cancel_wait(hapd);
1032 hostapd_dpp_listen_stop(hapd);
1033 dpp_auth_deinit(auth);
1034 hapd->dpp_auth = NULL;
1035 eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout,
1036 hapd, NULL);
1037}
1038
1039
Hai Shalom021b0b52019-04-10 11:17:58 -07001040#endif /* CONFIG_DPP2 */
1041
1042
Roshan Pius3a1667e2018-07-03 15:17:14 -07001043static void hostapd_dpp_send_peer_disc_resp(struct hostapd_data *hapd,
1044 const u8 *src, unsigned int freq,
1045 u8 trans_id,
1046 enum dpp_status_error status)
1047{
1048 struct wpabuf *msg;
1049
1050 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_RESP,
1051 5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector));
1052 if (!msg)
1053 return;
1054
1055#ifdef CONFIG_TESTING_OPTIONS
1056 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_RESP) {
1057 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
1058 goto skip_trans_id;
1059 }
1060 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_RESP) {
1061 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
1062 trans_id ^= 0x01;
1063 }
1064#endif /* CONFIG_TESTING_OPTIONS */
1065
1066 /* Transaction ID */
1067 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
1068 wpabuf_put_le16(msg, 1);
1069 wpabuf_put_u8(msg, trans_id);
1070
1071#ifdef CONFIG_TESTING_OPTIONS
1072skip_trans_id:
1073 if (dpp_test == DPP_TEST_NO_STATUS_PEER_DISC_RESP) {
1074 wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
1075 goto skip_status;
1076 }
1077 if (dpp_test == DPP_TEST_INVALID_STATUS_PEER_DISC_RESP) {
1078 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
1079 status = 254;
1080 }
1081#endif /* CONFIG_TESTING_OPTIONS */
1082
1083 /* DPP Status */
1084 wpabuf_put_le16(msg, DPP_ATTR_STATUS);
1085 wpabuf_put_le16(msg, 1);
1086 wpabuf_put_u8(msg, status);
1087
1088#ifdef CONFIG_TESTING_OPTIONS
1089skip_status:
1090 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_RESP) {
1091 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
1092 goto skip_connector;
1093 }
1094 if (status == DPP_STATUS_OK &&
1095 dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_RESP) {
1096 char *connector;
1097
1098 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
1099 connector = dpp_corrupt_connector_signature(
1100 hapd->conf->dpp_connector);
1101 if (!connector) {
1102 wpabuf_free(msg);
1103 return;
1104 }
1105 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
1106 wpabuf_put_le16(msg, os_strlen(connector));
1107 wpabuf_put_str(msg, connector);
1108 os_free(connector);
1109 goto skip_connector;
1110 }
1111#endif /* CONFIG_TESTING_OPTIONS */
1112
1113 /* DPP Connector */
1114 if (status == DPP_STATUS_OK) {
1115 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
1116 wpabuf_put_le16(msg, os_strlen(hapd->conf->dpp_connector));
1117 wpabuf_put_str(msg, hapd->conf->dpp_connector);
1118 }
1119
1120#ifdef CONFIG_TESTING_OPTIONS
1121skip_connector:
1122#endif /* CONFIG_TESTING_OPTIONS */
1123
1124 wpa_printf(MSG_DEBUG, "DPP: Send Peer Discovery Response to " MACSTR
1125 " status=%d", MAC2STR(src), status);
1126 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1127 " freq=%u type=%d status=%d", MAC2STR(src), freq,
1128 DPP_PA_PEER_DISCOVERY_RESP, status);
1129 hostapd_drv_send_action(hapd, freq, 0, src,
1130 wpabuf_head(msg), wpabuf_len(msg));
1131 wpabuf_free(msg);
1132}
1133
1134
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001135static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd,
1136 const u8 *src,
1137 const u8 *buf, size_t len,
1138 unsigned int freq)
1139{
1140 const u8 *connector, *trans_id;
1141 u16 connector_len, trans_id_len;
1142 struct os_time now;
1143 struct dpp_introduction intro;
1144 os_time_t expire;
1145 int expiration;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001146 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001147
1148 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Request from " MACSTR,
1149 MAC2STR(src));
1150 if (!hapd->wpa_auth ||
1151 !(hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) ||
1152 !(hapd->conf->wpa & WPA_PROTO_RSN)) {
1153 wpa_printf(MSG_DEBUG, "DPP: DPP AKM not in use");
1154 return;
1155 }
1156
1157 if (!hapd->conf->dpp_connector || !hapd->conf->dpp_netaccesskey ||
1158 !hapd->conf->dpp_csign) {
1159 wpa_printf(MSG_DEBUG, "DPP: No own Connector/keys set");
1160 return;
1161 }
1162
1163 os_get_time(&now);
1164
1165 if (hapd->conf->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001166 (os_time_t) hapd->conf->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001167 wpa_printf(MSG_INFO, "DPP: Own netAccessKey expired");
1168 return;
1169 }
1170
1171 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
1172 &trans_id_len);
1173 if (!trans_id || trans_id_len != 1) {
1174 wpa_printf(MSG_DEBUG,
1175 "DPP: Peer did not include Transaction ID");
1176 return;
1177 }
1178
1179 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
1180 if (!connector) {
1181 wpa_printf(MSG_DEBUG,
1182 "DPP: Peer did not include its Connector");
1183 return;
1184 }
1185
Roshan Pius3a1667e2018-07-03 15:17:14 -07001186 res = dpp_peer_intro(&intro, hapd->conf->dpp_connector,
1187 wpabuf_head(hapd->conf->dpp_netaccesskey),
1188 wpabuf_len(hapd->conf->dpp_netaccesskey),
1189 wpabuf_head(hapd->conf->dpp_csign),
1190 wpabuf_len(hapd->conf->dpp_csign),
1191 connector, connector_len, &expire);
1192 if (res == 255) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001193 wpa_printf(MSG_INFO,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001194 "DPP: Network Introduction protocol resulted in internal failure (peer "
1195 MACSTR ")", MAC2STR(src));
1196 return;
1197 }
1198 if (res != DPP_STATUS_OK) {
1199 wpa_printf(MSG_INFO,
1200 "DPP: Network Introduction protocol resulted in failure (peer "
1201 MACSTR " status %d)", MAC2STR(src), res);
1202 hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
1203 res);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001204 return;
1205 }
1206
Roshan Pius3a1667e2018-07-03 15:17:14 -07001207 if (!expire || (os_time_t) hapd->conf->dpp_netaccesskey_expiry < expire)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001208 expire = hapd->conf->dpp_netaccesskey_expiry;
1209 if (expire)
1210 expiration = expire - now.sec;
1211 else
1212 expiration = 0;
1213
1214 if (wpa_auth_pmksa_add2(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
1215 intro.pmkid, expiration,
1216 WPA_KEY_MGMT_DPP) < 0) {
1217 wpa_printf(MSG_ERROR, "DPP: Failed to add PMKSA cache entry");
1218 return;
1219 }
1220
Roshan Pius3a1667e2018-07-03 15:17:14 -07001221 hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
1222 DPP_STATUS_OK);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001223}
1224
1225
1226static void
1227hostapd_dpp_rx_pkex_exchange_req(struct hostapd_data *hapd, const u8 *src,
1228 const u8 *buf, size_t len,
1229 unsigned int freq)
1230{
1231 struct wpabuf *msg;
1232
1233 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
1234 MAC2STR(src));
1235
1236 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1237 * values here */
1238
1239 if (!hapd->dpp_pkex_code || !hapd->dpp_pkex_bi) {
1240 wpa_printf(MSG_DEBUG,
1241 "DPP: No PKEX code configured - ignore request");
1242 return;
1243 }
1244
1245 if (hapd->dpp_pkex) {
1246 /* TODO: Support parallel operations */
1247 wpa_printf(MSG_DEBUG,
1248 "DPP: Already in PKEX session - ignore new request");
1249 return;
1250 }
1251
Roshan Pius3a1667e2018-07-03 15:17:14 -07001252 hapd->dpp_pkex = dpp_pkex_rx_exchange_req(hapd->msg_ctx,
1253 hapd->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001254 hapd->own_addr, src,
1255 hapd->dpp_pkex_identifier,
1256 hapd->dpp_pkex_code,
1257 buf, len);
1258 if (!hapd->dpp_pkex) {
1259 wpa_printf(MSG_DEBUG,
1260 "DPP: Failed to process the request - ignore it");
1261 return;
1262 }
1263
1264 msg = hapd->dpp_pkex->exchange_resp;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001265 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1266 " freq=%u type=%d", MAC2STR(src), freq,
1267 DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001268 hostapd_drv_send_action(hapd, freq, 0, src,
1269 wpabuf_head(msg), wpabuf_len(msg));
Roshan Pius3a1667e2018-07-03 15:17:14 -07001270 if (hapd->dpp_pkex->failed) {
1271 wpa_printf(MSG_DEBUG,
1272 "DPP: Terminate PKEX exchange due to an earlier error");
1273 if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t)
1274 hapd->dpp_pkex->own_bi->pkex_t = hapd->dpp_pkex->t;
1275 dpp_pkex_free(hapd->dpp_pkex);
1276 hapd->dpp_pkex = NULL;
1277 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001278}
1279
1280
1281static void
1282hostapd_dpp_rx_pkex_exchange_resp(struct hostapd_data *hapd, const u8 *src,
1283 const u8 *buf, size_t len, unsigned int freq)
1284{
1285 struct wpabuf *msg;
1286
1287 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
1288 MAC2STR(src));
1289
1290 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1291 * values here */
1292
1293 if (!hapd->dpp_pkex || !hapd->dpp_pkex->initiator ||
1294 hapd->dpp_pkex->exchange_done) {
1295 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1296 return;
1297 }
1298
Roshan Pius3a1667e2018-07-03 15:17:14 -07001299 msg = dpp_pkex_rx_exchange_resp(hapd->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001300 if (!msg) {
1301 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
1302 return;
1303 }
1304
1305 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
1306 MAC2STR(src));
1307
Roshan Pius3a1667e2018-07-03 15:17:14 -07001308 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1309 " freq=%u type=%d", MAC2STR(src), freq,
1310 DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001311 hostapd_drv_send_action(hapd, freq, 0, src,
1312 wpabuf_head(msg), wpabuf_len(msg));
1313 wpabuf_free(msg);
1314}
1315
1316
1317static void
1318hostapd_dpp_rx_pkex_commit_reveal_req(struct hostapd_data *hapd, const u8 *src,
1319 const u8 *hdr, const u8 *buf, size_t len,
1320 unsigned int freq)
1321{
1322 struct wpabuf *msg;
1323 struct dpp_pkex *pkex = hapd->dpp_pkex;
1324 struct dpp_bootstrap_info *bi;
1325
1326 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
1327 MAC2STR(src));
1328
1329 if (!pkex || pkex->initiator || !pkex->exchange_done) {
1330 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1331 return;
1332 }
1333
1334 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
1335 if (!msg) {
1336 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001337 if (hapd->dpp_pkex->failed) {
1338 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
1339 if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t)
1340 hapd->dpp_pkex->own_bi->pkex_t =
1341 hapd->dpp_pkex->t;
1342 dpp_pkex_free(hapd->dpp_pkex);
1343 hapd->dpp_pkex = NULL;
1344 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001345 return;
1346 }
1347
1348 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
1349 MACSTR, MAC2STR(src));
1350
Roshan Pius3a1667e2018-07-03 15:17:14 -07001351 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1352 " freq=%u type=%d", MAC2STR(src), freq,
1353 DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001354 hostapd_drv_send_action(hapd, freq, 0, src,
1355 wpabuf_head(msg), wpabuf_len(msg));
1356 wpabuf_free(msg);
1357
Hai Shalom021b0b52019-04-10 11:17:58 -07001358 bi = dpp_pkex_finish(hapd->iface->interfaces->dpp, pkex, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001359 if (!bi)
1360 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001361 hapd->dpp_pkex = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001362}
1363
1364
1365static void
1366hostapd_dpp_rx_pkex_commit_reveal_resp(struct hostapd_data *hapd, const u8 *src,
1367 const u8 *hdr, const u8 *buf, size_t len,
1368 unsigned int freq)
1369{
1370 int res;
Hai Shalom021b0b52019-04-10 11:17:58 -07001371 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001372 struct dpp_pkex *pkex = hapd->dpp_pkex;
1373 char cmd[500];
1374
1375 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
1376 MAC2STR(src));
1377
1378 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
1379 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1380 return;
1381 }
1382
1383 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
1384 if (res < 0) {
1385 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
1386 return;
1387 }
1388
Hai Shalom021b0b52019-04-10 11:17:58 -07001389 bi = dpp_pkex_finish(hapd->iface->interfaces->dpp, pkex, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001390 if (!bi)
1391 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001392 hapd->dpp_pkex = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001393
1394 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
1395 bi->id,
1396 hapd->dpp_pkex_auth_cmd ? hapd->dpp_pkex_auth_cmd : "");
1397 wpa_printf(MSG_DEBUG,
1398 "DPP: Start authentication after PKEX with parameters: %s",
1399 cmd);
1400 if (hostapd_dpp_auth_init(hapd, cmd) < 0) {
1401 wpa_printf(MSG_DEBUG,
1402 "DPP: Authentication initialization failed");
1403 return;
1404 }
1405}
1406
1407
1408void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src,
1409 const u8 *buf, size_t len, unsigned int freq)
1410{
1411 u8 crypto_suite;
1412 enum dpp_public_action_frame_type type;
1413 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001414 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001415
1416 if (len < DPP_HDR_LEN)
1417 return;
1418 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
1419 return;
1420 hdr = buf;
1421 buf += 4;
1422 len -= 4;
1423 crypto_suite = *buf++;
1424 type = *buf++;
1425 len -= 2;
1426
1427 wpa_printf(MSG_DEBUG,
1428 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
1429 MACSTR " freq=%u",
1430 crypto_suite, type, MAC2STR(src), freq);
1431 if (crypto_suite != 1) {
1432 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
1433 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001434 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
1435 " freq=%u type=%d ignore=unsupported-crypto-suite",
1436 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001437 return;
1438 }
1439 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001440 if (dpp_check_attrs(buf, len) < 0) {
1441 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
1442 " freq=%u type=%d ignore=invalid-attributes",
1443 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001444 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001445 }
1446 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
1447 " freq=%u type=%d", MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001448
Hai Shalom81f62d82019-07-22 12:10:00 -07001449#ifdef CONFIG_DPP2
1450 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
1451 src, hdr, buf, len, freq, NULL, NULL) == 0)
1452 return;
1453#endif /* CONFIG_DPP2 */
1454
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001455 switch (type) {
1456 case DPP_PA_AUTHENTICATION_REQ:
1457 hostapd_dpp_rx_auth_req(hapd, src, hdr, buf, len, freq);
1458 break;
1459 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07001460 hostapd_dpp_rx_auth_resp(hapd, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001461 break;
1462 case DPP_PA_AUTHENTICATION_CONF:
1463 hostapd_dpp_rx_auth_conf(hapd, src, hdr, buf, len);
1464 break;
1465 case DPP_PA_PEER_DISCOVERY_REQ:
1466 hostapd_dpp_rx_peer_disc_req(hapd, src, buf, len, freq);
1467 break;
1468 case DPP_PA_PKEX_EXCHANGE_REQ:
1469 hostapd_dpp_rx_pkex_exchange_req(hapd, src, buf, len, freq);
1470 break;
1471 case DPP_PA_PKEX_EXCHANGE_RESP:
1472 hostapd_dpp_rx_pkex_exchange_resp(hapd, src, buf, len, freq);
1473 break;
1474 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
1475 hostapd_dpp_rx_pkex_commit_reveal_req(hapd, src, hdr, buf, len,
1476 freq);
1477 break;
1478 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
1479 hostapd_dpp_rx_pkex_commit_reveal_resp(hapd, src, hdr, buf, len,
1480 freq);
1481 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07001482#ifdef CONFIG_DPP2
1483 case DPP_PA_CONFIGURATION_RESULT:
1484 hostapd_dpp_rx_conf_result(hapd, src, hdr, buf, len);
1485 break;
Hai Shalomc3565922019-10-28 11:58:20 -07001486 case DPP_PA_CONNECTION_STATUS_RESULT:
1487 hostapd_dpp_rx_conn_status_result(hapd, src, hdr, buf, len);
1488 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07001489#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001490 default:
1491 wpa_printf(MSG_DEBUG,
1492 "DPP: Ignored unsupported frame subtype %d", type);
1493 break;
1494 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001495
1496 if (hapd->dpp_pkex)
1497 pkex_t = hapd->dpp_pkex->t;
1498 else if (hapd->dpp_pkex_bi)
1499 pkex_t = hapd->dpp_pkex_bi->pkex_t;
1500 else
1501 pkex_t = 0;
1502 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
1503 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
1504 hostapd_dpp_pkex_remove(hapd, "*");
1505 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001506}
1507
1508
1509struct wpabuf *
1510hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa,
Hai Shalom81f62d82019-07-22 12:10:00 -07001511 const u8 *query, size_t query_len,
1512 const u8 *data, size_t data_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001513{
1514 struct dpp_authentication *auth = hapd->dpp_auth;
1515 struct wpabuf *resp;
1516
1517 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa));
1518 if (!auth || !auth->auth_success ||
1519 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07001520#ifdef CONFIG_DPP2
1521 if (dpp_relay_rx_gas_req(hapd->iface->interfaces->dpp, sa, data,
1522 data_len) == 0) {
1523 /* Response will be forwarded once received over TCP */
1524 return NULL;
1525 }
1526#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001527 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1528 return NULL;
1529 }
1530 wpa_hexdump(MSG_DEBUG,
1531 "DPP: Received Configuration Request (GAS Query Request)",
1532 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001533 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
1534 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001535 resp = dpp_conf_req_rx(auth, query, query_len);
1536 if (!resp)
1537 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1538 return resp;
1539}
1540
1541
Roshan Pius3a1667e2018-07-03 15:17:14 -07001542void hostapd_dpp_gas_status_handler(struct hostapd_data *hapd, int ok)
1543{
Hai Shalom021b0b52019-04-10 11:17:58 -07001544 struct dpp_authentication *auth = hapd->dpp_auth;
1545
1546 if (!auth)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001547 return;
1548
Hai Shalom021b0b52019-04-10 11:17:58 -07001549 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
1550 ok);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001551 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
1552 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07001553#ifdef CONFIG_DPP2
1554 if (ok && auth->peer_version >= 2 &&
1555 auth->conf_resp_status == DPP_STATUS_OK) {
1556 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
1557 auth->waiting_conf_result = 1;
1558 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
1559 hapd, NULL);
1560 eloop_register_timeout(2, 0,
1561 hostapd_dpp_config_result_wait_timeout,
1562 hapd, NULL);
1563 return;
1564 }
1565#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001566 hostapd_drv_send_action_cancel_wait(hapd);
1567
1568 if (ok)
1569 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
1570 else
1571 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1572 dpp_auth_deinit(hapd->dpp_auth);
1573 hapd->dpp_auth = NULL;
1574}
1575
1576
Roshan Pius3a1667e2018-07-03 15:17:14 -07001577int hostapd_dpp_configurator_sign(struct hostapd_data *hapd, const char *cmd)
1578{
1579 struct dpp_authentication *auth;
1580 int ret = -1;
1581 char *curve = NULL;
1582
1583 auth = os_zalloc(sizeof(*auth));
1584 if (!auth)
1585 return -1;
1586
1587 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08001588 hostapd_dpp_set_testing_options(hapd, auth);
Hai Shalom021b0b52019-04-10 11:17:58 -07001589 if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx,
1590 auth, cmd) == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08001591 dpp_configurator_own_config(auth, curve, 1) == 0) {
Hai Shalomc3565922019-10-28 11:58:20 -07001592 hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001593 ret = 0;
1594 }
1595
1596 dpp_auth_deinit(auth);
1597 os_free(curve);
1598
1599 return ret;
1600}
1601
1602
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001603int hostapd_dpp_pkex_add(struct hostapd_data *hapd, const char *cmd)
1604{
1605 struct dpp_bootstrap_info *own_bi;
1606 const char *pos, *end;
1607
1608 pos = os_strstr(cmd, " own=");
1609 if (!pos)
1610 return -1;
1611 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -07001612 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001613 if (!own_bi) {
1614 wpa_printf(MSG_DEBUG,
1615 "DPP: Identified bootstrap info not found");
1616 return -1;
1617 }
1618 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
1619 wpa_printf(MSG_DEBUG,
1620 "DPP: Identified bootstrap info not for PKEX");
1621 return -1;
1622 }
1623 hapd->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001624 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001625
1626 os_free(hapd->dpp_pkex_identifier);
1627 hapd->dpp_pkex_identifier = NULL;
1628 pos = os_strstr(cmd, " identifier=");
1629 if (pos) {
1630 pos += 12;
1631 end = os_strchr(pos, ' ');
1632 if (!end)
1633 return -1;
1634 hapd->dpp_pkex_identifier = os_malloc(end - pos + 1);
1635 if (!hapd->dpp_pkex_identifier)
1636 return -1;
1637 os_memcpy(hapd->dpp_pkex_identifier, pos, end - pos);
1638 hapd->dpp_pkex_identifier[end - pos] = '\0';
1639 }
1640
1641 pos = os_strstr(cmd, " code=");
1642 if (!pos)
1643 return -1;
1644 os_free(hapd->dpp_pkex_code);
1645 hapd->dpp_pkex_code = os_strdup(pos + 6);
1646 if (!hapd->dpp_pkex_code)
1647 return -1;
1648
1649 if (os_strstr(cmd, " init=1")) {
1650 struct wpabuf *msg;
1651
1652 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
1653 dpp_pkex_free(hapd->dpp_pkex);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001654 hapd->dpp_pkex = dpp_pkex_init(hapd->msg_ctx, own_bi,
1655 hapd->own_addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001656 hapd->dpp_pkex_identifier,
1657 hapd->dpp_pkex_code);
1658 if (!hapd->dpp_pkex)
1659 return -1;
1660
1661 msg = hapd->dpp_pkex->exchange_req;
1662 /* TODO: Which channel to use? */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001663 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1664 " freq=%u type=%d", MAC2STR(broadcast), 2437,
1665 DPP_PA_PKEX_EXCHANGE_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001666 hostapd_drv_send_action(hapd, 2437, 0, broadcast,
1667 wpabuf_head(msg), wpabuf_len(msg));
1668 }
1669
1670 /* TODO: Support multiple PKEX info entries */
1671
1672 os_free(hapd->dpp_pkex_auth_cmd);
1673 hapd->dpp_pkex_auth_cmd = os_strdup(cmd);
1674
1675 return 1;
1676}
1677
1678
1679int hostapd_dpp_pkex_remove(struct hostapd_data *hapd, const char *id)
1680{
1681 unsigned int id_val;
1682
1683 if (os_strcmp(id, "*") == 0) {
1684 id_val = 0;
1685 } else {
1686 id_val = atoi(id);
1687 if (id_val == 0)
1688 return -1;
1689 }
1690
1691 if ((id_val != 0 && id_val != 1) || !hapd->dpp_pkex_code)
1692 return -1;
1693
1694 /* TODO: Support multiple PKEX entries */
1695 os_free(hapd->dpp_pkex_code);
1696 hapd->dpp_pkex_code = NULL;
1697 os_free(hapd->dpp_pkex_identifier);
1698 hapd->dpp_pkex_identifier = NULL;
1699 os_free(hapd->dpp_pkex_auth_cmd);
1700 hapd->dpp_pkex_auth_cmd = NULL;
1701 hapd->dpp_pkex_bi = NULL;
1702 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
1703 dpp_pkex_free(hapd->dpp_pkex);
1704 hapd->dpp_pkex = NULL;
1705 return 0;
1706}
1707
1708
Roshan Pius3a1667e2018-07-03 15:17:14 -07001709void hostapd_dpp_stop(struct hostapd_data *hapd)
1710{
1711 dpp_auth_deinit(hapd->dpp_auth);
1712 hapd->dpp_auth = NULL;
1713 dpp_pkex_free(hapd->dpp_pkex);
1714 hapd->dpp_pkex = NULL;
1715}
1716
1717
Hai Shalom81f62d82019-07-22 12:10:00 -07001718#ifdef CONFIG_DPP2
1719
1720static void hostapd_dpp_relay_tx(void *ctx, const u8 *addr, unsigned int freq,
1721 const u8 *msg, size_t len)
1722{
1723 struct hostapd_data *hapd = ctx;
1724 u8 *buf;
1725
1726 wpa_printf(MSG_DEBUG, "DPP: Send action frame dst=" MACSTR " freq=%u",
1727 MAC2STR(addr), freq);
1728 buf = os_malloc(2 + len);
1729 if (!buf)
1730 return;
1731 buf[0] = WLAN_ACTION_PUBLIC;
1732 buf[1] = WLAN_PA_VENDOR_SPECIFIC;
1733 os_memcpy(buf + 2, msg, len);
1734 hostapd_drv_send_action(hapd, freq, 0, addr, buf, 2 + len);
1735 os_free(buf);
1736}
1737
1738
1739static void hostapd_dpp_relay_gas_resp_tx(void *ctx, const u8 *addr,
1740 u8 dialog_token, int prot,
1741 struct wpabuf *buf)
1742{
1743 struct hostapd_data *hapd = ctx;
1744
1745 gas_serv_req_dpp_processing(hapd, addr, dialog_token, prot, buf);
1746}
1747
1748#endif /* CONFIG_DPP2 */
1749
1750
1751static int hostapd_dpp_add_controllers(struct hostapd_data *hapd)
1752{
1753#ifdef CONFIG_DPP2
1754 struct dpp_controller_conf *ctrl;
1755 struct dpp_relay_config config;
1756
1757 os_memset(&config, 0, sizeof(config));
1758 config.cb_ctx = hapd;
1759 config.tx = hostapd_dpp_relay_tx;
1760 config.gas_resp_tx = hostapd_dpp_relay_gas_resp_tx;
1761 for (ctrl = hapd->conf->dpp_controller; ctrl; ctrl = ctrl->next) {
1762 config.ipaddr = &ctrl->ipaddr;
1763 config.pkhash = ctrl->pkhash;
1764 if (dpp_relay_add_controller(hapd->iface->interfaces->dpp,
1765 &config) < 0)
1766 return -1;
1767 }
1768#endif /* CONFIG_DPP2 */
1769
1770 return 0;
1771}
1772
1773
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001774int hostapd_dpp_init(struct hostapd_data *hapd)
1775{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001776 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE;
1777 hapd->dpp_init_done = 1;
Hai Shalom81f62d82019-07-22 12:10:00 -07001778 return hostapd_dpp_add_controllers(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001779}
1780
1781
1782void hostapd_dpp_deinit(struct hostapd_data *hapd)
1783{
1784#ifdef CONFIG_TESTING_OPTIONS
1785 os_free(hapd->dpp_config_obj_override);
1786 hapd->dpp_config_obj_override = NULL;
1787 os_free(hapd->dpp_discovery_override);
1788 hapd->dpp_discovery_override = NULL;
1789 os_free(hapd->dpp_groups_override);
1790 hapd->dpp_groups_override = NULL;
1791 hapd->dpp_ignore_netaccesskey_mismatch = 0;
1792#endif /* CONFIG_TESTING_OPTIONS */
1793 if (!hapd->dpp_init_done)
1794 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001795 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
1796 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
1797 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07001798#ifdef CONFIG_DPP2
1799 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
1800 NULL);
Hai Shalomc3565922019-10-28 11:58:20 -07001801 eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout, hapd,
1802 NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07001803#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001804 dpp_auth_deinit(hapd->dpp_auth);
1805 hapd->dpp_auth = NULL;
1806 hostapd_dpp_pkex_remove(hapd, "*");
1807 hapd->dpp_pkex = NULL;
1808 os_free(hapd->dpp_configurator_params);
1809 hapd->dpp_configurator_params = NULL;
1810}