xref: /dragonfly/contrib/wpa_supplicant/src/ap/dpp_hostapd.c (revision 3a84a4273475ed07d0ab1c2dfeffdfedef35d9cd)
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  */
hostapd_dpp_qr_code(struct hostapd_data * hapd,const char * cmd)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 
hostapd_dpp_auth_resp_retry_timeout(void * eloop_ctx,void * timeout_ctx)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 
hostapd_dpp_auth_resp_retry(struct hostapd_data * hapd)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 
hostapd_dpp_tx_status(struct hostapd_data * hapd,const u8 * dst,const u8 * data,size_t data_len,int ok)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 
hostapd_dpp_reply_wait_timeout(void * eloop_ctx,void * timeout_ctx)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 
hostapd_dpp_set_testing_options(struct hostapd_data * hapd,struct dpp_authentication * auth)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 
hostapd_dpp_init_timeout(void * eloop_ctx,void * timeout_ctx)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 
hostapd_dpp_auth_init_next(struct hostapd_data * hapd)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 
hostapd_dpp_auth_init(struct hostapd_data * hapd,const char * cmd)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 
hostapd_dpp_listen(struct hostapd_data * hapd,const char * cmd)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 
hostapd_dpp_listen_stop(struct hostapd_data * hapd)517 void hostapd_dpp_listen_stop(struct hostapd_data *hapd)
518 {
519           /* TODO: Stop listen operation on non-operating channel */
520 }
521 
522 
hostapd_dpp_rx_auth_req(struct hostapd_data * hapd,const u8 * src,const u8 * hdr,const u8 * buf,size_t len,unsigned int freq)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 
hostapd_dpp_handle_config_obj(struct hostapd_data * hapd,struct dpp_authentication * auth)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 
hostapd_dpp_gas_resp_cb(void * ctx,const u8 * addr,u8 dialog_token,enum gas_query_ap_result result,const struct wpabuf * adv_proto,const struct wpabuf * resp,u16 status_code)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 
hostapd_dpp_start_gas_client(struct hostapd_data * hapd)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 
hostapd_dpp_auth_success(struct hostapd_data * hapd,int initiator)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 
hostapd_dpp_rx_auth_resp(struct hostapd_data * hapd,const u8 * src,const u8 * hdr,const u8 * buf,size_t len,unsigned int freq)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 
hostapd_dpp_rx_auth_conf(struct hostapd_data * hapd,const u8 * src,const u8 * hdr,const u8 * buf,size_t len)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 
hostapd_dpp_config_result_wait_timeout(void * eloop_ctx,void * timeout_ctx)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 
hostapd_dpp_rx_conf_result(struct hostapd_data * hapd,const u8 * src,const u8 * hdr,const u8 * buf,size_t len)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 
hostapd_dpp_send_peer_disc_resp(struct hostapd_data * hapd,const u8 * src,unsigned int freq,u8 trans_id,enum dpp_status_error status)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 
hostapd_dpp_rx_peer_disc_req(struct hostapd_data * hapd,const u8 * src,const u8 * buf,size_t len,unsigned int freq)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
hostapd_dpp_rx_pkex_exchange_req(struct hostapd_data * hapd,const u8 * src,const u8 * buf,size_t len,unsigned int freq)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
hostapd_dpp_rx_pkex_exchange_resp(struct hostapd_data * hapd,const u8 * src,const u8 * buf,size_t len,unsigned int freq)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
hostapd_dpp_rx_pkex_commit_reveal_req(struct hostapd_data * hapd,const u8 * src,const u8 * hdr,const u8 * buf,size_t len,unsigned int freq)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
hostapd_dpp_rx_pkex_commit_reveal_resp(struct hostapd_data * hapd,const u8 * src,const u8 * hdr,const u8 * buf,size_t len,unsigned int freq)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 
hostapd_dpp_rx_action(struct hostapd_data * hapd,const u8 * src,const u8 * buf,size_t len,unsigned int freq)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 *
hostapd_dpp_gas_req_handler(struct hostapd_data * hapd,const u8 * sa,const u8 * query,size_t query_len,const u8 * data,size_t data_len)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 
hostapd_dpp_gas_status_handler(struct hostapd_data * hapd,int ok)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 
hostapd_dpp_configurator_sign(struct hostapd_data * hapd,const char * cmd)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 
hostapd_dpp_pkex_add(struct hostapd_data * hapd,const char * cmd)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 
hostapd_dpp_pkex_remove(struct hostapd_data * hapd,const char * id)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 
hostapd_dpp_stop(struct hostapd_data * hapd)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 
hostapd_dpp_relay_tx(void * ctx,const u8 * addr,unsigned int freq,const u8 * msg,size_t len)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 
hostapd_dpp_relay_gas_resp_tx(void * ctx,const u8 * addr,u8 dialog_token,int prot,struct wpabuf * buf)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 
hostapd_dpp_add_controllers(struct hostapd_data * hapd)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 
hostapd_dpp_init(struct hostapd_data * hapd)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 
hostapd_dpp_deinit(struct hostapd_data * hapd)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 }
1726