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