blob: 75edbc909e7a022429f6feb4ae68deaddbb59ddd [file] [log] [blame]
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001/*
2 * hostapd / DPP integration
3 * Copyright (c) 2017, Qualcomm Atheros, Inc.
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9#include "utils/includes.h"
10
11#include "utils/common.h"
12#include "utils/eloop.h"
13#include "common/dpp.h"
14#include "common/gas.h"
15#include "common/wpa_ctrl.h"
16#include "hostapd.h"
17#include "ap_drv_ops.h"
18#include "gas_query_ap.h"
19#include "wpa_auth.h"
20#include "dpp_hostapd.h"
21
22
Roshan Pius3a1667e2018-07-03 15:17:14 -070023static void hostapd_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070024static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator);
Roshan Pius3a1667e2018-07-03 15:17:14 -070025static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx);
26static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070027
28static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
29
30
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070031/**
32 * hostapd_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
33 * @hapd: Pointer to hostapd_data
34 * @cmd: DPP URI read from a QR Code
35 * Returns: Identifier of the stored info or -1 on failure
36 */
37int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd)
38{
39 struct dpp_bootstrap_info *bi;
40 struct dpp_authentication *auth = hapd->dpp_auth;
41
Hai Shalom021b0b52019-04-10 11:17:58 -070042 bi = dpp_add_qr_code(hapd->iface->interfaces->dpp, cmd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070043 if (!bi)
44 return -1;
45
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070046 if (auth && auth->response_pending &&
47 dpp_notify_new_qr_code(auth, bi) == 1) {
48 wpa_printf(MSG_DEBUG,
49 "DPP: Sending out pending authentication response");
Roshan Pius3a1667e2018-07-03 15:17:14 -070050 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
51 " freq=%u type=%d",
52 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
53 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070054 hostapd_drv_send_action(hapd, auth->curr_freq, 0,
55 auth->peer_mac_addr,
56 wpabuf_head(hapd->dpp_auth->resp_msg),
57 wpabuf_len(hapd->dpp_auth->resp_msg));
58 }
59
60 return bi->id;
61}
62
63
Roshan Pius3a1667e2018-07-03 15:17:14 -070064static void hostapd_dpp_auth_resp_retry_timeout(void *eloop_ctx,
65 void *timeout_ctx)
66{
67 struct hostapd_data *hapd = eloop_ctx;
68 struct dpp_authentication *auth = hapd->dpp_auth;
69
70 if (!auth || !auth->resp_msg)
71 return;
72
73 wpa_printf(MSG_DEBUG,
74 "DPP: Retry Authentication Response after timeout");
75 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
76 " freq=%u type=%d",
77 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
78 DPP_PA_AUTHENTICATION_RESP);
79 hostapd_drv_send_action(hapd, auth->curr_freq, 500, auth->peer_mac_addr,
80 wpabuf_head(auth->resp_msg),
81 wpabuf_len(auth->resp_msg));
82}
83
84
85static void hostapd_dpp_auth_resp_retry(struct hostapd_data *hapd)
86{
87 struct dpp_authentication *auth = hapd->dpp_auth;
88 unsigned int wait_time, max_tries;
89
90 if (!auth || !auth->resp_msg)
91 return;
92
93 if (hapd->dpp_resp_max_tries)
94 max_tries = hapd->dpp_resp_max_tries;
95 else
96 max_tries = 5;
97 auth->auth_resp_tries++;
98 if (auth->auth_resp_tries >= max_tries) {
99 wpa_printf(MSG_INFO,
100 "DPP: No confirm received from initiator - stopping exchange");
101 hostapd_drv_send_action_cancel_wait(hapd);
102 dpp_auth_deinit(hapd->dpp_auth);
103 hapd->dpp_auth = NULL;
104 return;
105 }
106
107 if (hapd->dpp_resp_retry_time)
108 wait_time = hapd->dpp_resp_retry_time;
109 else
110 wait_time = 1000;
111 wpa_printf(MSG_DEBUG,
112 "DPP: Schedule retransmission of Authentication Response frame in %u ms",
113 wait_time);
114 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
115 eloop_register_timeout(wait_time / 1000,
116 (wait_time % 1000) * 1000,
117 hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
118}
119
120
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700121void hostapd_dpp_tx_status(struct hostapd_data *hapd, const u8 *dst,
122 const u8 *data, size_t data_len, int ok)
123{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700124 struct dpp_authentication *auth = hapd->dpp_auth;
125
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700126 wpa_printf(MSG_DEBUG, "DPP: TX status: dst=" MACSTR " ok=%d",
127 MAC2STR(dst), ok);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700128 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
129 " result=%s", MAC2STR(dst), ok ? "SUCCESS" : "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700130
131 if (!hapd->dpp_auth) {
132 wpa_printf(MSG_DEBUG,
133 "DPP: Ignore TX status since there is no ongoing authentication exchange");
134 return;
135 }
136
Hai Shalom021b0b52019-04-10 11:17:58 -0700137#ifdef CONFIG_DPP2
138 if (auth->connect_on_tx_status) {
139 wpa_printf(MSG_DEBUG,
140 "DPP: Complete exchange on configuration result");
141 dpp_auth_deinit(hapd->dpp_auth);
142 hapd->dpp_auth = NULL;
143 return;
144 }
145#endif /* CONFIG_DPP2 */
146
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700147 if (hapd->dpp_auth->remove_on_tx_status) {
148 wpa_printf(MSG_DEBUG,
149 "DPP: Terminate authentication exchange due to an earlier error");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700150 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
151 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
152 hapd, NULL);
153 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
154 NULL);
155 hostapd_drv_send_action_cancel_wait(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700156 dpp_auth_deinit(hapd->dpp_auth);
157 hapd->dpp_auth = NULL;
158 return;
159 }
160
161 if (hapd->dpp_auth_ok_on_ack)
162 hostapd_dpp_auth_success(hapd, 1);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700163
164 if (!is_broadcast_ether_addr(dst) && !ok) {
165 wpa_printf(MSG_DEBUG,
166 "DPP: Unicast DPP Action frame was not ACKed");
167 if (auth->waiting_auth_resp) {
168 /* In case of DPP Authentication Request frame, move to
169 * the next channel immediately. */
170 hostapd_drv_send_action_cancel_wait(hapd);
171 hostapd_dpp_auth_init_next(hapd);
172 return;
173 }
174 if (auth->waiting_auth_conf) {
175 hostapd_dpp_auth_resp_retry(hapd);
176 return;
177 }
178 }
179
180 if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp && ok) {
181 /* Allow timeout handling to stop iteration if no response is
182 * received from a peer that has ACKed a request. */
183 auth->auth_req_ack = 1;
184 }
185
186 if (!hapd->dpp_auth_ok_on_ack && hapd->dpp_auth->neg_freq > 0 &&
187 hapd->dpp_auth->curr_freq != hapd->dpp_auth->neg_freq) {
188 wpa_printf(MSG_DEBUG,
189 "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response",
190 hapd->dpp_auth->curr_freq,
191 hapd->dpp_auth->neg_freq);
192 hostapd_drv_send_action_cancel_wait(hapd);
193
194 if (hapd->dpp_auth->neg_freq !=
195 (unsigned int) hapd->iface->freq && hapd->iface->freq > 0) {
196 /* TODO: Listen operation on non-operating channel */
197 wpa_printf(MSG_INFO,
198 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
199 hapd->dpp_auth->neg_freq, hapd->iface->freq);
200 }
201 }
202
203 if (hapd->dpp_auth_ok_on_ack)
204 hapd->dpp_auth_ok_on_ack = 0;
205}
206
207
208static void hostapd_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx)
209{
210 struct hostapd_data *hapd = eloop_ctx;
211 struct dpp_authentication *auth = hapd->dpp_auth;
212 unsigned int freq;
213 struct os_reltime now, diff;
214 unsigned int wait_time, diff_ms;
215
216 if (!auth || !auth->waiting_auth_resp)
217 return;
218
219 wait_time = hapd->dpp_resp_wait_time ?
220 hapd->dpp_resp_wait_time : 2000;
221 os_get_reltime(&now);
222 os_reltime_sub(&now, &hapd->dpp_last_init, &diff);
223 diff_ms = diff.sec * 1000 + diff.usec / 1000;
224 wpa_printf(MSG_DEBUG,
225 "DPP: Reply wait timeout - wait_time=%u diff_ms=%u",
226 wait_time, diff_ms);
227
228 if (auth->auth_req_ack && diff_ms >= wait_time) {
229 /* Peer ACK'ed Authentication Request frame, but did not reply
230 * with Authentication Response frame within two seconds. */
231 wpa_printf(MSG_INFO,
232 "DPP: No response received from responder - stopping initiation attempt");
233 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
234 hostapd_drv_send_action_cancel_wait(hapd);
235 hostapd_dpp_listen_stop(hapd);
236 dpp_auth_deinit(auth);
237 hapd->dpp_auth = NULL;
238 return;
239 }
240
241 if (diff_ms >= wait_time) {
242 /* Authentication Request frame was not ACK'ed and no reply
243 * was receiving within two seconds. */
244 wpa_printf(MSG_DEBUG,
245 "DPP: Continue Initiator channel iteration");
246 hostapd_drv_send_action_cancel_wait(hapd);
247 hostapd_dpp_listen_stop(hapd);
248 hostapd_dpp_auth_init_next(hapd);
249 return;
250 }
251
252 /* Driver did not support 2000 ms long wait_time with TX command, so
253 * schedule listen operation to continue waiting for the response.
254 *
255 * DPP listen operations continue until stopped, so simply schedule a
256 * new call to this function at the point when the two second reply
257 * wait has expired. */
258 wait_time -= diff_ms;
259
260 freq = auth->curr_freq;
261 if (auth->neg_freq > 0)
262 freq = auth->neg_freq;
263 wpa_printf(MSG_DEBUG,
264 "DPP: Continue reply wait on channel %u MHz for %u ms",
265 freq, wait_time);
266 hapd->dpp_in_response_listen = 1;
267
268 if (freq != (unsigned int) hapd->iface->freq && hapd->iface->freq > 0) {
269 /* TODO: Listen operation on non-operating channel */
270 wpa_printf(MSG_INFO,
271 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
272 freq, hapd->iface->freq);
273 }
274
275 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
276 hostapd_dpp_reply_wait_timeout, hapd, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700277}
278
279
280static void hostapd_dpp_set_testing_options(struct hostapd_data *hapd,
281 struct dpp_authentication *auth)
282{
283#ifdef CONFIG_TESTING_OPTIONS
284 if (hapd->dpp_config_obj_override)
285 auth->config_obj_override =
286 os_strdup(hapd->dpp_config_obj_override);
287 if (hapd->dpp_discovery_override)
288 auth->discovery_override =
289 os_strdup(hapd->dpp_discovery_override);
290 if (hapd->dpp_groups_override)
291 auth->groups_override = os_strdup(hapd->dpp_groups_override);
292 auth->ignore_netaccesskey_mismatch =
293 hapd->dpp_ignore_netaccesskey_mismatch;
294#endif /* CONFIG_TESTING_OPTIONS */
295}
296
297
Roshan Pius3a1667e2018-07-03 15:17:14 -0700298static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
299{
300 struct hostapd_data *hapd = eloop_ctx;
301
302 if (!hapd->dpp_auth)
303 return;
304 wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout");
305 hostapd_dpp_auth_init_next(hapd);
306}
307
308
309static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd)
310{
311 struct dpp_authentication *auth = hapd->dpp_auth;
312 const u8 *dst;
313 unsigned int wait_time, max_wait_time, freq, max_tries, used;
314 struct os_reltime now, diff;
315
316 if (!auth)
317 return -1;
318
319 if (auth->freq_idx == 0)
320 os_get_reltime(&hapd->dpp_init_iter_start);
321
322 if (auth->freq_idx >= auth->num_freq) {
323 auth->num_freq_iters++;
324 if (hapd->dpp_init_max_tries)
325 max_tries = hapd->dpp_init_max_tries;
326 else
327 max_tries = 5;
328 if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) {
329 wpa_printf(MSG_INFO,
330 "DPP: No response received from responder - stopping initiation attempt");
331 wpa_msg(hapd->msg_ctx, MSG_INFO,
332 DPP_EVENT_AUTH_INIT_FAILED);
333 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
334 hapd, NULL);
335 hostapd_drv_send_action_cancel_wait(hapd);
336 dpp_auth_deinit(hapd->dpp_auth);
337 hapd->dpp_auth = NULL;
338 return -1;
339 }
340 auth->freq_idx = 0;
341 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
342 if (hapd->dpp_init_retry_time)
343 wait_time = hapd->dpp_init_retry_time;
344 else
345 wait_time = 10000;
346 os_get_reltime(&now);
347 os_reltime_sub(&now, &hapd->dpp_init_iter_start, &diff);
348 used = diff.sec * 1000 + diff.usec / 1000;
349 if (used > wait_time)
350 wait_time = 0;
351 else
352 wait_time -= used;
353 wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms",
354 wait_time);
355 eloop_register_timeout(wait_time / 1000,
356 (wait_time % 1000) * 1000,
357 hostapd_dpp_init_timeout, hapd,
358 NULL);
359 return 0;
360 }
361 freq = auth->freq[auth->freq_idx++];
362 auth->curr_freq = freq;
363
364 if (is_zero_ether_addr(auth->peer_bi->mac_addr))
365 dst = broadcast;
366 else
367 dst = auth->peer_bi->mac_addr;
368 hapd->dpp_auth_ok_on_ack = 0;
369 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
370 wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
371 max_wait_time = hapd->dpp_resp_wait_time ?
372 hapd->dpp_resp_wait_time : 2000;
373 if (wait_time > max_wait_time)
374 wait_time = max_wait_time;
375 wait_time += 10; /* give the driver some extra time to complete */
376 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
377 hostapd_dpp_reply_wait_timeout, hapd, NULL);
378 wait_time -= 10;
379 if (auth->neg_freq > 0 && freq != auth->neg_freq) {
380 wpa_printf(MSG_DEBUG,
381 "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response",
382 freq, auth->neg_freq);
383 }
384 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
385 " freq=%u type=%d",
386 MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ);
387 auth->auth_req_ack = 0;
388 os_get_reltime(&hapd->dpp_last_init);
389 return hostapd_drv_send_action(hapd, freq, wait_time,
390 dst,
391 wpabuf_head(hapd->dpp_auth->req_msg),
392 wpabuf_len(hapd->dpp_auth->req_msg));
393}
394
395
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700396int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
397{
398 const char *pos;
399 struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700400 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
401 unsigned int neg_freq = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700402
403 pos = os_strstr(cmd, " peer=");
404 if (!pos)
405 return -1;
406 pos += 6;
Hai Shalom021b0b52019-04-10 11:17:58 -0700407 peer_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700408 if (!peer_bi) {
409 wpa_printf(MSG_INFO,
410 "DPP: Could not find bootstrapping info for the identified peer");
411 return -1;
412 }
413
414 pos = os_strstr(cmd, " own=");
415 if (pos) {
416 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -0700417 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp,
418 atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700419 if (!own_bi) {
420 wpa_printf(MSG_INFO,
421 "DPP: Could not find bootstrapping info for the identified local entry");
422 return -1;
423 }
424
425 if (peer_bi->curve != own_bi->curve) {
426 wpa_printf(MSG_INFO,
427 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
428 peer_bi->curve->name, own_bi->curve->name);
429 return -1;
430 }
431 }
432
433 pos = os_strstr(cmd, " role=");
434 if (pos) {
435 pos += 6;
436 if (os_strncmp(pos, "configurator", 12) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700437 allowed_roles = DPP_CAPAB_CONFIGURATOR;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700438 else if (os_strncmp(pos, "enrollee", 8) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700439 allowed_roles = DPP_CAPAB_ENROLLEE;
440 else if (os_strncmp(pos, "either", 6) == 0)
441 allowed_roles = DPP_CAPAB_CONFIGURATOR |
442 DPP_CAPAB_ENROLLEE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700443 else
444 goto fail;
445 }
446
Roshan Pius3a1667e2018-07-03 15:17:14 -0700447 pos = os_strstr(cmd, " neg_freq=");
448 if (pos)
449 neg_freq = atoi(pos + 10);
450
451 if (hapd->dpp_auth) {
452 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
453 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
454 hapd, NULL);
455 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
456 NULL);
457 hostapd_drv_send_action_cancel_wait(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700458 dpp_auth_deinit(hapd->dpp_auth);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700459 }
460
461 hapd->dpp_auth = dpp_auth_init(hapd->msg_ctx, peer_bi, own_bi,
462 allowed_roles, neg_freq,
463 hapd->iface->hw_features,
464 hapd->iface->num_hw_features);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700465 if (!hapd->dpp_auth)
466 goto fail;
467 hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
Hai Shalom021b0b52019-04-10 11:17:58 -0700468 if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx,
469 hapd->dpp_auth, cmd) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -0800470 dpp_auth_deinit(hapd->dpp_auth);
471 hapd->dpp_auth = NULL;
472 goto fail;
473 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700474
Roshan Pius3a1667e2018-07-03 15:17:14 -0700475 hapd->dpp_auth->neg_freq = neg_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700476
Roshan Pius3a1667e2018-07-03 15:17:14 -0700477 if (!is_zero_ether_addr(peer_bi->mac_addr))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700478 os_memcpy(hapd->dpp_auth->peer_mac_addr, peer_bi->mac_addr,
479 ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700480
Roshan Pius3a1667e2018-07-03 15:17:14 -0700481 return hostapd_dpp_auth_init_next(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700482fail:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700483 return -1;
484}
485
486
Roshan Pius3a1667e2018-07-03 15:17:14 -0700487int hostapd_dpp_listen(struct hostapd_data *hapd, const char *cmd)
488{
489 int freq;
490
491 freq = atoi(cmd);
492 if (freq <= 0)
493 return -1;
494
495 if (os_strstr(cmd, " role=configurator"))
496 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
497 else if (os_strstr(cmd, " role=enrollee"))
498 hapd->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
499 else
500 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
501 DPP_CAPAB_ENROLLEE;
502 hapd->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
503
504 if (freq != hapd->iface->freq && hapd->iface->freq > 0) {
505 /* TODO: Listen operation on non-operating channel */
506 wpa_printf(MSG_INFO,
507 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
508 freq, hapd->iface->freq);
509 return -1;
510 }
511
512 return 0;
513}
514
515
516void hostapd_dpp_listen_stop(struct hostapd_data *hapd)
517{
518 /* TODO: Stop listen operation on non-operating channel */
519}
520
521
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700522static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src,
523 const u8 *hdr, const u8 *buf, size_t len,
524 unsigned int freq)
525{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700526 const u8 *r_bootstrap, *i_bootstrap;
527 u16 r_bootstrap_len, i_bootstrap_len;
Hai Shalom021b0b52019-04-10 11:17:58 -0700528 struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
529
530 if (!hapd->iface->interfaces->dpp)
531 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700532
533 wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
534 MAC2STR(src));
535
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700536 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
537 &r_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700538 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
539 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
540 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700541 return;
542 }
543 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
544 r_bootstrap, r_bootstrap_len);
545
546 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
547 &i_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700548 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
549 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
550 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700551 return;
552 }
553 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
554 i_bootstrap, i_bootstrap_len);
555
556 /* Try to find own and peer bootstrapping key matches based on the
557 * received hash values */
Hai Shalom021b0b52019-04-10 11:17:58 -0700558 dpp_bootstrap_find_pair(hapd->iface->interfaces->dpp, i_bootstrap,
559 r_bootstrap, &own_bi, &peer_bi);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700560 if (!own_bi) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700561 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
562 "No matching own bootstrapping key found - ignore message");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700563 return;
564 }
565
566 if (hapd->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700567 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
568 "Already in DPP authentication exchange - ignore new one");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700569 return;
570 }
571
572 hapd->dpp_auth_ok_on_ack = 0;
573 hapd->dpp_auth = dpp_auth_req_rx(hapd->msg_ctx, hapd->dpp_allowed_roles,
574 hapd->dpp_qr_mutual,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700575 peer_bi, own_bi, freq, hdr, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700576 if (!hapd->dpp_auth) {
577 wpa_printf(MSG_DEBUG, "DPP: No response generated");
578 return;
579 }
580 hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
Hai Shalom021b0b52019-04-10 11:17:58 -0700581 if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx,
582 hapd->dpp_auth,
583 hapd->dpp_configurator_params) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -0800584 dpp_auth_deinit(hapd->dpp_auth);
585 hapd->dpp_auth = NULL;
586 return;
587 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700588 os_memcpy(hapd->dpp_auth->peer_mac_addr, src, ETH_ALEN);
589
Roshan Pius3a1667e2018-07-03 15:17:14 -0700590 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
591 " freq=%u type=%d",
592 MAC2STR(src), hapd->dpp_auth->curr_freq,
593 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700594 hostapd_drv_send_action(hapd, hapd->dpp_auth->curr_freq, 0,
595 src, wpabuf_head(hapd->dpp_auth->resp_msg),
596 wpabuf_len(hapd->dpp_auth->resp_msg));
597}
598
599
Roshan Pius3a1667e2018-07-03 15:17:14 -0700600static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd,
601 struct dpp_authentication *auth)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700602{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700603 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700604 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
605 dpp_akm_str(auth->akm));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700606 if (auth->ssid_len)
607 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
608 wpa_ssid_txt(auth->ssid, auth->ssid_len));
609 if (auth->connector) {
610 /* TODO: Save the Connector and consider using a command
611 * to fetch the value instead of sending an event with
612 * it. The Connector could end up being larger than what
613 * most clients are ready to receive as an event
614 * message. */
615 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
616 auth->connector);
617 } else if (auth->passphrase[0]) {
618 char hex[64 * 2 + 1];
619
620 wpa_snprintf_hex(hex, sizeof(hex),
621 (const u8 *) auth->passphrase,
622 os_strlen(auth->passphrase));
623 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
624 hex);
625 } else if (auth->psk_set) {
626 char hex[PMK_LEN * 2 + 1];
627
628 wpa_snprintf_hex(hex, sizeof(hex), auth->psk, PMK_LEN);
629 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
630 hex);
631 }
632 if (auth->c_sign_key) {
633 char *hex;
634 size_t hexlen;
635
636 hexlen = 2 * wpabuf_len(auth->c_sign_key) + 1;
637 hex = os_malloc(hexlen);
638 if (hex) {
639 wpa_snprintf_hex(hex, hexlen,
640 wpabuf_head(auth->c_sign_key),
641 wpabuf_len(auth->c_sign_key));
642 wpa_msg(hapd->msg_ctx, MSG_INFO,
643 DPP_EVENT_C_SIGN_KEY "%s", hex);
644 os_free(hex);
645 }
646 }
647 if (auth->net_access_key) {
648 char *hex;
649 size_t hexlen;
650
651 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
652 hex = os_malloc(hexlen);
653 if (hex) {
654 wpa_snprintf_hex(hex, hexlen,
655 wpabuf_head(auth->net_access_key),
656 wpabuf_len(auth->net_access_key));
657 if (auth->net_access_key_expiry)
658 wpa_msg(hapd->msg_ctx, MSG_INFO,
659 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
660 (unsigned long)
661 auth->net_access_key_expiry);
662 else
663 wpa_msg(hapd->msg_ctx, MSG_INFO,
664 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
665 os_free(hex);
666 }
667 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700668}
669
670
671static void hostapd_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
672 enum gas_query_ap_result result,
673 const struct wpabuf *adv_proto,
674 const struct wpabuf *resp, u16 status_code)
675{
676 struct hostapd_data *hapd = ctx;
677 const u8 *pos;
678 struct dpp_authentication *auth = hapd->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -0700679 enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700680
681 if (!auth || !auth->auth_success) {
682 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
683 return;
684 }
685 if (!resp || status_code != WLAN_STATUS_SUCCESS) {
686 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
687 goto fail;
688 }
689
690 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
691 adv_proto);
692 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
693 resp);
694
695 if (wpabuf_len(adv_proto) != 10 ||
696 !(pos = wpabuf_head(adv_proto)) ||
697 pos[0] != WLAN_EID_ADV_PROTO ||
698 pos[1] != 8 ||
699 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
700 pos[4] != 5 ||
701 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
702 pos[8] != 0x1a ||
703 pos[9] != 1) {
704 wpa_printf(MSG_DEBUG,
705 "DPP: Not a DPP Advertisement Protocol ID");
706 goto fail;
707 }
708
709 if (dpp_conf_resp_rx(auth, resp) < 0) {
710 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
711 goto fail;
712 }
713
714 hostapd_dpp_handle_config_obj(hapd, auth);
Hai Shalom021b0b52019-04-10 11:17:58 -0700715 status = DPP_STATUS_OK;
716#ifdef CONFIG_TESTING_OPTIONS
717 if (dpp_test == DPP_TEST_REJECT_CONFIG) {
718 wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object");
719 status = DPP_STATUS_CONFIG_REJECTED;
720 }
721#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700722fail:
Hai Shalom021b0b52019-04-10 11:17:58 -0700723 if (status != DPP_STATUS_OK)
724 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
725#ifdef CONFIG_DPP2
726 if (auth->peer_version >= 2 &&
727 auth->conf_resp_status == DPP_STATUS_OK) {
728 struct wpabuf *msg;
729
730 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
731 msg = dpp_build_conf_result(auth, status);
732 if (!msg)
733 goto fail2;
734
735 wpa_msg(hapd->msg_ctx, MSG_INFO,
736 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
737 MAC2STR(addr), auth->curr_freq,
738 DPP_PA_CONFIGURATION_RESULT);
739 hostapd_drv_send_action(hapd, auth->curr_freq, 0,
740 addr, wpabuf_head(msg),
741 wpabuf_len(msg));
742 wpabuf_free(msg);
743
744 /* This exchange will be terminated in the TX status handler */
745 auth->connect_on_tx_status = 1;
746 return;
747 }
748fail2:
749#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700750 dpp_auth_deinit(hapd->dpp_auth);
751 hapd->dpp_auth = NULL;
752}
753
754
755static void hostapd_dpp_start_gas_client(struct hostapd_data *hapd)
756{
757 struct dpp_authentication *auth = hapd->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -0700758 struct wpabuf *buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700759 char json[100];
760 int res;
761 int netrole_ap = 1;
762
763 os_snprintf(json, sizeof(json),
764 "{\"name\":\"Test\","
765 "\"wi-fi_tech\":\"infra\","
766 "\"netRole\":\"%s\"}",
767 netrole_ap ? "ap" : "sta");
768 wpa_printf(MSG_DEBUG, "DPP: GAS Config Attributes: %s", json);
769
Hai Shalom021b0b52019-04-10 11:17:58 -0700770 buf = dpp_build_conf_req(auth, json);
771 if (!buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700772 wpa_printf(MSG_DEBUG,
773 "DPP: No configuration request data available");
774 return;
775 }
776
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700777 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
778 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
779
780 res = gas_query_ap_req(hapd->gas, auth->peer_mac_addr, auth->curr_freq,
781 buf, hostapd_dpp_gas_resp_cb, hapd);
782 if (res < 0) {
783 wpa_msg(hapd->msg_ctx, MSG_DEBUG,
784 "GAS: Failed to send Query Request");
785 wpabuf_free(buf);
786 } else {
787 wpa_printf(MSG_DEBUG,
788 "DPP: GAS query started with dialog token %u", res);
789 }
790}
791
792
793static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator)
794{
795 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
796 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d",
797 initiator);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700798#ifdef CONFIG_TESTING_OPTIONS
799 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
800 wpa_printf(MSG_INFO,
801 "DPP: TESTING - stop at Authentication Confirm");
802 if (hapd->dpp_auth->configurator) {
803 /* Prevent GAS response */
804 hapd->dpp_auth->auth_success = 0;
805 }
806 return;
807 }
808#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700809
810 if (!hapd->dpp_auth->configurator)
811 hostapd_dpp_start_gas_client(hapd);
812}
813
814
815static void hostapd_dpp_rx_auth_resp(struct hostapd_data *hapd, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700816 const u8 *hdr, const u8 *buf, size_t len,
817 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700818{
819 struct dpp_authentication *auth = hapd->dpp_auth;
820 struct wpabuf *msg;
821
822 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR,
823 MAC2STR(src));
824
825 if (!auth) {
826 wpa_printf(MSG_DEBUG,
827 "DPP: No DPP Authentication in progress - drop");
828 return;
829 }
830
831 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
832 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
833 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
834 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
835 return;
836 }
837
Roshan Pius3a1667e2018-07-03 15:17:14 -0700838 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
839
840 if (auth->curr_freq != freq && auth->neg_freq == freq) {
841 wpa_printf(MSG_DEBUG,
842 "DPP: Responder accepted request for different negotiation channel");
843 auth->curr_freq = freq;
844 }
845
846 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700847 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
848 if (!msg) {
849 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
850 wpa_printf(MSG_DEBUG, "DPP: Wait for full response");
851 return;
852 }
853 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
854 return;
855 }
856 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
857
Roshan Pius3a1667e2018-07-03 15:17:14 -0700858 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
859 " freq=%u type=%d", MAC2STR(src), auth->curr_freq,
860 DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700861 hostapd_drv_send_action(hapd, auth->curr_freq, 0, src,
862 wpabuf_head(msg), wpabuf_len(msg));
863 wpabuf_free(msg);
864 hapd->dpp_auth_ok_on_ack = 1;
865}
866
867
868static void hostapd_dpp_rx_auth_conf(struct hostapd_data *hapd, const u8 *src,
869 const u8 *hdr, const u8 *buf, size_t len)
870{
871 struct dpp_authentication *auth = hapd->dpp_auth;
872
873 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
874 MAC2STR(src));
875
876 if (!auth) {
877 wpa_printf(MSG_DEBUG,
878 "DPP: No DPP Authentication in progress - drop");
879 return;
880 }
881
882 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
883 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
884 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
885 return;
886 }
887
888 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
889 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
890 return;
891 }
892
893 hostapd_dpp_auth_success(hapd, 0);
894}
895
896
Hai Shalom021b0b52019-04-10 11:17:58 -0700897#ifdef CONFIG_DPP2
898
899static void hostapd_dpp_config_result_wait_timeout(void *eloop_ctx,
900 void *timeout_ctx)
901{
902 struct hostapd_data *hapd = eloop_ctx;
903 struct dpp_authentication *auth = hapd->dpp_auth;
904
905 if (!auth || !auth->waiting_conf_result)
906 return;
907
908 wpa_printf(MSG_DEBUG,
909 "DPP: Timeout while waiting for Configuration Result");
910 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
911 dpp_auth_deinit(auth);
912 hapd->dpp_auth = NULL;
913}
914
915
916static void hostapd_dpp_rx_conf_result(struct hostapd_data *hapd, const u8 *src,
917 const u8 *hdr, const u8 *buf, size_t len)
918{
919 struct dpp_authentication *auth = hapd->dpp_auth;
920 enum dpp_status_error status;
921
922 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
923 MAC2STR(src));
924
925 if (!auth || !auth->waiting_conf_result) {
926 wpa_printf(MSG_DEBUG,
927 "DPP: No DPP Configuration waiting for result - drop");
928 return;
929 }
930
931 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
932 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
933 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
934 return;
935 }
936
937 status = dpp_conf_result_rx(auth, hdr, buf, len);
938
939 hostapd_drv_send_action_cancel_wait(hapd);
940 hostapd_dpp_listen_stop(hapd);
941 if (status == DPP_STATUS_OK)
942 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
943 else
944 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
945 dpp_auth_deinit(auth);
946 hapd->dpp_auth = NULL;
947 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
948 NULL);
949}
950
951#endif /* CONFIG_DPP2 */
952
953
Roshan Pius3a1667e2018-07-03 15:17:14 -0700954static void hostapd_dpp_send_peer_disc_resp(struct hostapd_data *hapd,
955 const u8 *src, unsigned int freq,
956 u8 trans_id,
957 enum dpp_status_error status)
958{
959 struct wpabuf *msg;
960
961 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_RESP,
962 5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector));
963 if (!msg)
964 return;
965
966#ifdef CONFIG_TESTING_OPTIONS
967 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_RESP) {
968 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
969 goto skip_trans_id;
970 }
971 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_RESP) {
972 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
973 trans_id ^= 0x01;
974 }
975#endif /* CONFIG_TESTING_OPTIONS */
976
977 /* Transaction ID */
978 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
979 wpabuf_put_le16(msg, 1);
980 wpabuf_put_u8(msg, trans_id);
981
982#ifdef CONFIG_TESTING_OPTIONS
983skip_trans_id:
984 if (dpp_test == DPP_TEST_NO_STATUS_PEER_DISC_RESP) {
985 wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
986 goto skip_status;
987 }
988 if (dpp_test == DPP_TEST_INVALID_STATUS_PEER_DISC_RESP) {
989 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
990 status = 254;
991 }
992#endif /* CONFIG_TESTING_OPTIONS */
993
994 /* DPP Status */
995 wpabuf_put_le16(msg, DPP_ATTR_STATUS);
996 wpabuf_put_le16(msg, 1);
997 wpabuf_put_u8(msg, status);
998
999#ifdef CONFIG_TESTING_OPTIONS
1000skip_status:
1001 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_RESP) {
1002 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
1003 goto skip_connector;
1004 }
1005 if (status == DPP_STATUS_OK &&
1006 dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_RESP) {
1007 char *connector;
1008
1009 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
1010 connector = dpp_corrupt_connector_signature(
1011 hapd->conf->dpp_connector);
1012 if (!connector) {
1013 wpabuf_free(msg);
1014 return;
1015 }
1016 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
1017 wpabuf_put_le16(msg, os_strlen(connector));
1018 wpabuf_put_str(msg, connector);
1019 os_free(connector);
1020 goto skip_connector;
1021 }
1022#endif /* CONFIG_TESTING_OPTIONS */
1023
1024 /* DPP Connector */
1025 if (status == DPP_STATUS_OK) {
1026 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
1027 wpabuf_put_le16(msg, os_strlen(hapd->conf->dpp_connector));
1028 wpabuf_put_str(msg, hapd->conf->dpp_connector);
1029 }
1030
1031#ifdef CONFIG_TESTING_OPTIONS
1032skip_connector:
1033#endif /* CONFIG_TESTING_OPTIONS */
1034
1035 wpa_printf(MSG_DEBUG, "DPP: Send Peer Discovery Response to " MACSTR
1036 " status=%d", MAC2STR(src), status);
1037 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1038 " freq=%u type=%d status=%d", MAC2STR(src), freq,
1039 DPP_PA_PEER_DISCOVERY_RESP, status);
1040 hostapd_drv_send_action(hapd, freq, 0, src,
1041 wpabuf_head(msg), wpabuf_len(msg));
1042 wpabuf_free(msg);
1043}
1044
1045
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001046static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd,
1047 const u8 *src,
1048 const u8 *buf, size_t len,
1049 unsigned int freq)
1050{
1051 const u8 *connector, *trans_id;
1052 u16 connector_len, trans_id_len;
1053 struct os_time now;
1054 struct dpp_introduction intro;
1055 os_time_t expire;
1056 int expiration;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001057 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001058
1059 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Request from " MACSTR,
1060 MAC2STR(src));
1061 if (!hapd->wpa_auth ||
1062 !(hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) ||
1063 !(hapd->conf->wpa & WPA_PROTO_RSN)) {
1064 wpa_printf(MSG_DEBUG, "DPP: DPP AKM not in use");
1065 return;
1066 }
1067
1068 if (!hapd->conf->dpp_connector || !hapd->conf->dpp_netaccesskey ||
1069 !hapd->conf->dpp_csign) {
1070 wpa_printf(MSG_DEBUG, "DPP: No own Connector/keys set");
1071 return;
1072 }
1073
1074 os_get_time(&now);
1075
1076 if (hapd->conf->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001077 (os_time_t) hapd->conf->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001078 wpa_printf(MSG_INFO, "DPP: Own netAccessKey expired");
1079 return;
1080 }
1081
1082 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
1083 &trans_id_len);
1084 if (!trans_id || trans_id_len != 1) {
1085 wpa_printf(MSG_DEBUG,
1086 "DPP: Peer did not include Transaction ID");
1087 return;
1088 }
1089
1090 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
1091 if (!connector) {
1092 wpa_printf(MSG_DEBUG,
1093 "DPP: Peer did not include its Connector");
1094 return;
1095 }
1096
Roshan Pius3a1667e2018-07-03 15:17:14 -07001097 res = dpp_peer_intro(&intro, hapd->conf->dpp_connector,
1098 wpabuf_head(hapd->conf->dpp_netaccesskey),
1099 wpabuf_len(hapd->conf->dpp_netaccesskey),
1100 wpabuf_head(hapd->conf->dpp_csign),
1101 wpabuf_len(hapd->conf->dpp_csign),
1102 connector, connector_len, &expire);
1103 if (res == 255) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001104 wpa_printf(MSG_INFO,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001105 "DPP: Network Introduction protocol resulted in internal failure (peer "
1106 MACSTR ")", MAC2STR(src));
1107 return;
1108 }
1109 if (res != DPP_STATUS_OK) {
1110 wpa_printf(MSG_INFO,
1111 "DPP: Network Introduction protocol resulted in failure (peer "
1112 MACSTR " status %d)", MAC2STR(src), res);
1113 hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
1114 res);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001115 return;
1116 }
1117
Roshan Pius3a1667e2018-07-03 15:17:14 -07001118 if (!expire || (os_time_t) hapd->conf->dpp_netaccesskey_expiry < expire)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001119 expire = hapd->conf->dpp_netaccesskey_expiry;
1120 if (expire)
1121 expiration = expire - now.sec;
1122 else
1123 expiration = 0;
1124
1125 if (wpa_auth_pmksa_add2(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
1126 intro.pmkid, expiration,
1127 WPA_KEY_MGMT_DPP) < 0) {
1128 wpa_printf(MSG_ERROR, "DPP: Failed to add PMKSA cache entry");
1129 return;
1130 }
1131
Roshan Pius3a1667e2018-07-03 15:17:14 -07001132 hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
1133 DPP_STATUS_OK);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001134}
1135
1136
1137static void
1138hostapd_dpp_rx_pkex_exchange_req(struct hostapd_data *hapd, const u8 *src,
1139 const u8 *buf, size_t len,
1140 unsigned int freq)
1141{
1142 struct wpabuf *msg;
1143
1144 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
1145 MAC2STR(src));
1146
1147 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1148 * values here */
1149
1150 if (!hapd->dpp_pkex_code || !hapd->dpp_pkex_bi) {
1151 wpa_printf(MSG_DEBUG,
1152 "DPP: No PKEX code configured - ignore request");
1153 return;
1154 }
1155
1156 if (hapd->dpp_pkex) {
1157 /* TODO: Support parallel operations */
1158 wpa_printf(MSG_DEBUG,
1159 "DPP: Already in PKEX session - ignore new request");
1160 return;
1161 }
1162
Roshan Pius3a1667e2018-07-03 15:17:14 -07001163 hapd->dpp_pkex = dpp_pkex_rx_exchange_req(hapd->msg_ctx,
1164 hapd->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001165 hapd->own_addr, src,
1166 hapd->dpp_pkex_identifier,
1167 hapd->dpp_pkex_code,
1168 buf, len);
1169 if (!hapd->dpp_pkex) {
1170 wpa_printf(MSG_DEBUG,
1171 "DPP: Failed to process the request - ignore it");
1172 return;
1173 }
1174
1175 msg = hapd->dpp_pkex->exchange_resp;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001176 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1177 " freq=%u type=%d", MAC2STR(src), freq,
1178 DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001179 hostapd_drv_send_action(hapd, freq, 0, src,
1180 wpabuf_head(msg), wpabuf_len(msg));
Roshan Pius3a1667e2018-07-03 15:17:14 -07001181 if (hapd->dpp_pkex->failed) {
1182 wpa_printf(MSG_DEBUG,
1183 "DPP: Terminate PKEX exchange due to an earlier error");
1184 if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t)
1185 hapd->dpp_pkex->own_bi->pkex_t = hapd->dpp_pkex->t;
1186 dpp_pkex_free(hapd->dpp_pkex);
1187 hapd->dpp_pkex = NULL;
1188 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001189}
1190
1191
1192static void
1193hostapd_dpp_rx_pkex_exchange_resp(struct hostapd_data *hapd, const u8 *src,
1194 const u8 *buf, size_t len, unsigned int freq)
1195{
1196 struct wpabuf *msg;
1197
1198 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
1199 MAC2STR(src));
1200
1201 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1202 * values here */
1203
1204 if (!hapd->dpp_pkex || !hapd->dpp_pkex->initiator ||
1205 hapd->dpp_pkex->exchange_done) {
1206 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1207 return;
1208 }
1209
Roshan Pius3a1667e2018-07-03 15:17:14 -07001210 msg = dpp_pkex_rx_exchange_resp(hapd->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001211 if (!msg) {
1212 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
1213 return;
1214 }
1215
1216 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
1217 MAC2STR(src));
1218
Roshan Pius3a1667e2018-07-03 15:17:14 -07001219 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1220 " freq=%u type=%d", MAC2STR(src), freq,
1221 DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001222 hostapd_drv_send_action(hapd, freq, 0, src,
1223 wpabuf_head(msg), wpabuf_len(msg));
1224 wpabuf_free(msg);
1225}
1226
1227
1228static void
1229hostapd_dpp_rx_pkex_commit_reveal_req(struct hostapd_data *hapd, const u8 *src,
1230 const u8 *hdr, const u8 *buf, size_t len,
1231 unsigned int freq)
1232{
1233 struct wpabuf *msg;
1234 struct dpp_pkex *pkex = hapd->dpp_pkex;
1235 struct dpp_bootstrap_info *bi;
1236
1237 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
1238 MAC2STR(src));
1239
1240 if (!pkex || pkex->initiator || !pkex->exchange_done) {
1241 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1242 return;
1243 }
1244
1245 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
1246 if (!msg) {
1247 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001248 if (hapd->dpp_pkex->failed) {
1249 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
1250 if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t)
1251 hapd->dpp_pkex->own_bi->pkex_t =
1252 hapd->dpp_pkex->t;
1253 dpp_pkex_free(hapd->dpp_pkex);
1254 hapd->dpp_pkex = NULL;
1255 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001256 return;
1257 }
1258
1259 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
1260 MACSTR, MAC2STR(src));
1261
Roshan Pius3a1667e2018-07-03 15:17:14 -07001262 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1263 " freq=%u type=%d", MAC2STR(src), freq,
1264 DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001265 hostapd_drv_send_action(hapd, freq, 0, src,
1266 wpabuf_head(msg), wpabuf_len(msg));
1267 wpabuf_free(msg);
1268
Hai Shalom021b0b52019-04-10 11:17:58 -07001269 bi = dpp_pkex_finish(hapd->iface->interfaces->dpp, pkex, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001270 if (!bi)
1271 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001272 hapd->dpp_pkex = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001273}
1274
1275
1276static void
1277hostapd_dpp_rx_pkex_commit_reveal_resp(struct hostapd_data *hapd, const u8 *src,
1278 const u8 *hdr, const u8 *buf, size_t len,
1279 unsigned int freq)
1280{
1281 int res;
Hai Shalom021b0b52019-04-10 11:17:58 -07001282 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001283 struct dpp_pkex *pkex = hapd->dpp_pkex;
1284 char cmd[500];
1285
1286 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
1287 MAC2STR(src));
1288
1289 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
1290 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1291 return;
1292 }
1293
1294 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
1295 if (res < 0) {
1296 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
1297 return;
1298 }
1299
Hai Shalom021b0b52019-04-10 11:17:58 -07001300 bi = dpp_pkex_finish(hapd->iface->interfaces->dpp, pkex, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001301 if (!bi)
1302 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001303 hapd->dpp_pkex = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001304
1305 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
1306 bi->id,
1307 hapd->dpp_pkex_auth_cmd ? hapd->dpp_pkex_auth_cmd : "");
1308 wpa_printf(MSG_DEBUG,
1309 "DPP: Start authentication after PKEX with parameters: %s",
1310 cmd);
1311 if (hostapd_dpp_auth_init(hapd, cmd) < 0) {
1312 wpa_printf(MSG_DEBUG,
1313 "DPP: Authentication initialization failed");
1314 return;
1315 }
1316}
1317
1318
1319void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src,
1320 const u8 *buf, size_t len, unsigned int freq)
1321{
1322 u8 crypto_suite;
1323 enum dpp_public_action_frame_type type;
1324 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001325 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001326
1327 if (len < DPP_HDR_LEN)
1328 return;
1329 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
1330 return;
1331 hdr = buf;
1332 buf += 4;
1333 len -= 4;
1334 crypto_suite = *buf++;
1335 type = *buf++;
1336 len -= 2;
1337
1338 wpa_printf(MSG_DEBUG,
1339 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
1340 MACSTR " freq=%u",
1341 crypto_suite, type, MAC2STR(src), freq);
1342 if (crypto_suite != 1) {
1343 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
1344 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001345 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
1346 " freq=%u type=%d ignore=unsupported-crypto-suite",
1347 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001348 return;
1349 }
1350 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001351 if (dpp_check_attrs(buf, len) < 0) {
1352 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
1353 " freq=%u type=%d ignore=invalid-attributes",
1354 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001355 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001356 }
1357 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
1358 " freq=%u type=%d", MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001359
1360 switch (type) {
1361 case DPP_PA_AUTHENTICATION_REQ:
1362 hostapd_dpp_rx_auth_req(hapd, src, hdr, buf, len, freq);
1363 break;
1364 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07001365 hostapd_dpp_rx_auth_resp(hapd, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001366 break;
1367 case DPP_PA_AUTHENTICATION_CONF:
1368 hostapd_dpp_rx_auth_conf(hapd, src, hdr, buf, len);
1369 break;
1370 case DPP_PA_PEER_DISCOVERY_REQ:
1371 hostapd_dpp_rx_peer_disc_req(hapd, src, buf, len, freq);
1372 break;
1373 case DPP_PA_PKEX_EXCHANGE_REQ:
1374 hostapd_dpp_rx_pkex_exchange_req(hapd, src, buf, len, freq);
1375 break;
1376 case DPP_PA_PKEX_EXCHANGE_RESP:
1377 hostapd_dpp_rx_pkex_exchange_resp(hapd, src, buf, len, freq);
1378 break;
1379 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
1380 hostapd_dpp_rx_pkex_commit_reveal_req(hapd, src, hdr, buf, len,
1381 freq);
1382 break;
1383 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
1384 hostapd_dpp_rx_pkex_commit_reveal_resp(hapd, src, hdr, buf, len,
1385 freq);
1386 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07001387#ifdef CONFIG_DPP2
1388 case DPP_PA_CONFIGURATION_RESULT:
1389 hostapd_dpp_rx_conf_result(hapd, src, hdr, buf, len);
1390 break;
1391#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001392 default:
1393 wpa_printf(MSG_DEBUG,
1394 "DPP: Ignored unsupported frame subtype %d", type);
1395 break;
1396 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001397
1398 if (hapd->dpp_pkex)
1399 pkex_t = hapd->dpp_pkex->t;
1400 else if (hapd->dpp_pkex_bi)
1401 pkex_t = hapd->dpp_pkex_bi->pkex_t;
1402 else
1403 pkex_t = 0;
1404 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
1405 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
1406 hostapd_dpp_pkex_remove(hapd, "*");
1407 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001408}
1409
1410
1411struct wpabuf *
1412hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa,
1413 const u8 *query, size_t query_len)
1414{
1415 struct dpp_authentication *auth = hapd->dpp_auth;
1416 struct wpabuf *resp;
1417
1418 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa));
1419 if (!auth || !auth->auth_success ||
1420 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
1421 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1422 return NULL;
1423 }
1424 wpa_hexdump(MSG_DEBUG,
1425 "DPP: Received Configuration Request (GAS Query Request)",
1426 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001427 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
1428 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001429 resp = dpp_conf_req_rx(auth, query, query_len);
1430 if (!resp)
1431 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1432 return resp;
1433}
1434
1435
Roshan Pius3a1667e2018-07-03 15:17:14 -07001436void hostapd_dpp_gas_status_handler(struct hostapd_data *hapd, int ok)
1437{
Hai Shalom021b0b52019-04-10 11:17:58 -07001438 struct dpp_authentication *auth = hapd->dpp_auth;
1439
1440 if (!auth)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001441 return;
1442
Hai Shalom021b0b52019-04-10 11:17:58 -07001443 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
1444 ok);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001445 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
1446 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07001447#ifdef CONFIG_DPP2
1448 if (ok && auth->peer_version >= 2 &&
1449 auth->conf_resp_status == DPP_STATUS_OK) {
1450 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
1451 auth->waiting_conf_result = 1;
1452 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
1453 hapd, NULL);
1454 eloop_register_timeout(2, 0,
1455 hostapd_dpp_config_result_wait_timeout,
1456 hapd, NULL);
1457 return;
1458 }
1459#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001460 hostapd_drv_send_action_cancel_wait(hapd);
1461
1462 if (ok)
1463 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
1464 else
1465 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1466 dpp_auth_deinit(hapd->dpp_auth);
1467 hapd->dpp_auth = NULL;
1468}
1469
1470
Roshan Pius3a1667e2018-07-03 15:17:14 -07001471int hostapd_dpp_configurator_sign(struct hostapd_data *hapd, const char *cmd)
1472{
1473 struct dpp_authentication *auth;
1474 int ret = -1;
1475 char *curve = NULL;
1476
1477 auth = os_zalloc(sizeof(*auth));
1478 if (!auth)
1479 return -1;
1480
1481 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08001482 hostapd_dpp_set_testing_options(hapd, auth);
Hai Shalom021b0b52019-04-10 11:17:58 -07001483 if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx,
1484 auth, cmd) == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08001485 dpp_configurator_own_config(auth, curve, 1) == 0) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001486 hostapd_dpp_handle_config_obj(hapd, auth);
1487 ret = 0;
1488 }
1489
1490 dpp_auth_deinit(auth);
1491 os_free(curve);
1492
1493 return ret;
1494}
1495
1496
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001497int hostapd_dpp_pkex_add(struct hostapd_data *hapd, const char *cmd)
1498{
1499 struct dpp_bootstrap_info *own_bi;
1500 const char *pos, *end;
1501
1502 pos = os_strstr(cmd, " own=");
1503 if (!pos)
1504 return -1;
1505 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -07001506 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001507 if (!own_bi) {
1508 wpa_printf(MSG_DEBUG,
1509 "DPP: Identified bootstrap info not found");
1510 return -1;
1511 }
1512 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
1513 wpa_printf(MSG_DEBUG,
1514 "DPP: Identified bootstrap info not for PKEX");
1515 return -1;
1516 }
1517 hapd->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001518 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001519
1520 os_free(hapd->dpp_pkex_identifier);
1521 hapd->dpp_pkex_identifier = NULL;
1522 pos = os_strstr(cmd, " identifier=");
1523 if (pos) {
1524 pos += 12;
1525 end = os_strchr(pos, ' ');
1526 if (!end)
1527 return -1;
1528 hapd->dpp_pkex_identifier = os_malloc(end - pos + 1);
1529 if (!hapd->dpp_pkex_identifier)
1530 return -1;
1531 os_memcpy(hapd->dpp_pkex_identifier, pos, end - pos);
1532 hapd->dpp_pkex_identifier[end - pos] = '\0';
1533 }
1534
1535 pos = os_strstr(cmd, " code=");
1536 if (!pos)
1537 return -1;
1538 os_free(hapd->dpp_pkex_code);
1539 hapd->dpp_pkex_code = os_strdup(pos + 6);
1540 if (!hapd->dpp_pkex_code)
1541 return -1;
1542
1543 if (os_strstr(cmd, " init=1")) {
1544 struct wpabuf *msg;
1545
1546 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
1547 dpp_pkex_free(hapd->dpp_pkex);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001548 hapd->dpp_pkex = dpp_pkex_init(hapd->msg_ctx, own_bi,
1549 hapd->own_addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001550 hapd->dpp_pkex_identifier,
1551 hapd->dpp_pkex_code);
1552 if (!hapd->dpp_pkex)
1553 return -1;
1554
1555 msg = hapd->dpp_pkex->exchange_req;
1556 /* TODO: Which channel to use? */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001557 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1558 " freq=%u type=%d", MAC2STR(broadcast), 2437,
1559 DPP_PA_PKEX_EXCHANGE_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001560 hostapd_drv_send_action(hapd, 2437, 0, broadcast,
1561 wpabuf_head(msg), wpabuf_len(msg));
1562 }
1563
1564 /* TODO: Support multiple PKEX info entries */
1565
1566 os_free(hapd->dpp_pkex_auth_cmd);
1567 hapd->dpp_pkex_auth_cmd = os_strdup(cmd);
1568
1569 return 1;
1570}
1571
1572
1573int hostapd_dpp_pkex_remove(struct hostapd_data *hapd, const char *id)
1574{
1575 unsigned int id_val;
1576
1577 if (os_strcmp(id, "*") == 0) {
1578 id_val = 0;
1579 } else {
1580 id_val = atoi(id);
1581 if (id_val == 0)
1582 return -1;
1583 }
1584
1585 if ((id_val != 0 && id_val != 1) || !hapd->dpp_pkex_code)
1586 return -1;
1587
1588 /* TODO: Support multiple PKEX entries */
1589 os_free(hapd->dpp_pkex_code);
1590 hapd->dpp_pkex_code = NULL;
1591 os_free(hapd->dpp_pkex_identifier);
1592 hapd->dpp_pkex_identifier = NULL;
1593 os_free(hapd->dpp_pkex_auth_cmd);
1594 hapd->dpp_pkex_auth_cmd = NULL;
1595 hapd->dpp_pkex_bi = NULL;
1596 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
1597 dpp_pkex_free(hapd->dpp_pkex);
1598 hapd->dpp_pkex = NULL;
1599 return 0;
1600}
1601
1602
Roshan Pius3a1667e2018-07-03 15:17:14 -07001603void hostapd_dpp_stop(struct hostapd_data *hapd)
1604{
1605 dpp_auth_deinit(hapd->dpp_auth);
1606 hapd->dpp_auth = NULL;
1607 dpp_pkex_free(hapd->dpp_pkex);
1608 hapd->dpp_pkex = NULL;
1609}
1610
1611
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001612int hostapd_dpp_init(struct hostapd_data *hapd)
1613{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001614 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE;
1615 hapd->dpp_init_done = 1;
1616 return 0;
1617}
1618
1619
1620void hostapd_dpp_deinit(struct hostapd_data *hapd)
1621{
1622#ifdef CONFIG_TESTING_OPTIONS
1623 os_free(hapd->dpp_config_obj_override);
1624 hapd->dpp_config_obj_override = NULL;
1625 os_free(hapd->dpp_discovery_override);
1626 hapd->dpp_discovery_override = NULL;
1627 os_free(hapd->dpp_groups_override);
1628 hapd->dpp_groups_override = NULL;
1629 hapd->dpp_ignore_netaccesskey_mismatch = 0;
1630#endif /* CONFIG_TESTING_OPTIONS */
1631 if (!hapd->dpp_init_done)
1632 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001633 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
1634 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
1635 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07001636#ifdef CONFIG_DPP2
1637 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
1638 NULL);
1639#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001640 dpp_auth_deinit(hapd->dpp_auth);
1641 hapd->dpp_auth = NULL;
1642 hostapd_dpp_pkex_remove(hapd, "*");
1643 hapd->dpp_pkex = NULL;
1644 os_free(hapd->dpp_configurator_params);
1645 hapd->dpp_configurator_params = NULL;
1646}