1 /**
2 * Copyright (c) 2023 Nordic Semiconductor ASA
3 * Copyright 2024 NXP
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7 #include <stdarg.h>
8
9 #include <zephyr/logging/log.h>
10 #include <zephyr/kernel.h>
11 #include <zephyr/net/wifi_mgmt.h>
12
13 #include "includes.h"
14 #include "common.h"
15 #include "common/defs.h"
16 #include "common/ieee802_11_defs.h"
17 #include "common/ieee802_11_common.h"
18 #include "wpa_supplicant/config.h"
19 #include "wpa_supplicant_i.h"
20 #include "driver_i.h"
21
22 #include "supp_main.h"
23 #include "supp_api.h"
24 #include "wpa_cli_zephyr.h"
25 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
26 #include "hostapd.h"
27 #include "hostapd_cli_zephyr.h"
28 #include "ap_drv_ops.h"
29 #endif
30 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
31 #include "eap_peer/eap.h"
32 #endif
33 #include "supp_events.h"
34 #include "wpa_supplicant/bss.h"
35
36 extern struct k_sem wpa_supplicant_ready_sem;
37 extern struct wpa_global *global;
38
39 /* save the last wifi connection parameters */
40 static struct wifi_connect_req_params last_wifi_conn_params;
41
42 enum requested_ops {
43 CONNECT = 0,
44 DISCONNECT,
45 WPS_PBC,
46 WPS_PIN,
47 };
48
49 enum status_thread_state {
50 STATUS_THREAD_STOPPED = 0,
51 STATUS_THREAD_RUNNING,
52 };
53
54 #define OP_STATUS_POLLING_INTERVAL 1
55
56 #define CONNECTION_SUCCESS 0
57 #define CONNECTION_FAILURE 1
58 #define CONNECTION_TERMINATED 2
59
60 #define DISCONNECT_TIMEOUT_MS 5000
61
62 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
63 static struct wifi_enterprise_creds_params enterprise_creds;
64 #endif
65
66 K_MUTEX_DEFINE(wpa_supplicant_mutex);
67
68 extern struct k_work_q *get_workq(void);
69
70 struct wpa_supp_api_ctrl {
71 const struct device *dev;
72 enum requested_ops requested_op;
73 enum status_thread_state status_thread_state;
74 int connection_timeout; /* in seconds */
75 struct k_work_sync sync;
76 bool terminate;
77 };
78
79 static struct wpa_supp_api_ctrl wpas_api_ctrl;
80
81 static void supp_shell_connect_status(struct k_work *work);
82
83 static K_WORK_DELAYABLE_DEFINE(wpa_supp_status_work,
84 supp_shell_connect_status);
85
86 #define wpa_cli_cmd_v(cmd, ...) ({ \
87 bool status; \
88 \
89 if (zephyr_wpa_cli_cmd_v(cmd, ##__VA_ARGS__) < 0) { \
90 wpa_printf(MSG_ERROR, \
91 "Failed to execute wpa_cli command: %s", \
92 cmd); \
93 status = false; \
94 } else { \
95 status = true; \
96 } \
97 \
98 status; \
99 })
100
get_wpa_s_handle(const struct device * dev)101 static struct wpa_supplicant *get_wpa_s_handle(const struct device *dev)
102 {
103 struct net_if *iface = net_if_lookup_by_dev(dev);
104 char if_name[CONFIG_NET_INTERFACE_NAME_LEN + 1];
105 struct wpa_supplicant *wpa_s;
106 int ret;
107
108 if (!iface) {
109 wpa_printf(MSG_ERROR, "Interface for device %s not found", dev->name);
110 return NULL;
111 }
112
113 ret = net_if_get_name(iface, if_name, sizeof(if_name));
114 if (!ret) {
115 wpa_printf(MSG_ERROR, "Cannot get interface name (%d)", ret);
116 return NULL;
117 }
118
119 wpa_s = zephyr_get_handle_by_ifname(if_name);
120 if (!wpa_s) {
121 wpa_printf(MSG_ERROR, "Interface %s not found", if_name);
122 return NULL;
123 }
124
125 return wpa_s;
126 }
127
128 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
129 #define hostapd_cli_cmd_v(cmd, ...) ({ \
130 bool status; \
131 \
132 if (zephyr_hostapd_cli_cmd_v(cmd, ##__VA_ARGS__) < 0) { \
133 wpa_printf(MSG_ERROR, \
134 "Failed to execute wpa_cli command: %s", \
135 cmd); \
136 status = false; \
137 } else { \
138 status = true; \
139 } \
140 \
141 status; \
142 })
143
get_hostapd_handle(const struct device * dev)144 static inline struct hostapd_iface *get_hostapd_handle(const struct device *dev)
145 {
146 struct net_if *iface = net_if_lookup_by_dev(dev);
147 char if_name[CONFIG_NET_INTERFACE_NAME_LEN + 1];
148 struct hostapd_iface *hapd;
149 int ret;
150
151 if (!iface) {
152 wpa_printf(MSG_ERROR, "Interface for device %s not found", dev->name);
153 return NULL;
154 }
155
156 ret = net_if_get_name(iface, if_name, sizeof(if_name));
157 if (!ret) {
158 wpa_printf(MSG_ERROR, "Cannot get interface name (%d)", ret);
159 return NULL;
160 }
161
162 hapd = zephyr_get_hapd_handle_by_ifname(if_name);
163 if (!hapd) {
164 wpa_printf(MSG_ERROR, "Interface %s not found", if_name);
165 return NULL;
166 }
167
168 return hapd;
169 }
170 #endif
171
172 #define WPA_SUPP_STATE_POLLING_MS 10
wait_for_disconnect_complete(const struct device * dev)173 static int wait_for_disconnect_complete(const struct device *dev)
174 {
175 int ret = 0;
176 int attempts = 0;
177 struct wpa_supplicant *wpa_s = get_wpa_s_handle(dev);
178 unsigned int max_attempts = DISCONNECT_TIMEOUT_MS / WPA_SUPP_STATE_POLLING_MS;
179
180 if (!wpa_s) {
181 ret = -ENODEV;
182 wpa_printf(MSG_ERROR, "Failed to get wpa_s handle");
183 goto out;
184 }
185
186 while (wpa_s->wpa_state != WPA_DISCONNECTED) {
187 if (attempts++ > max_attempts) {
188 ret = -ETIMEDOUT;
189 wpa_printf(MSG_WARNING, "Failed to disconnect from network");
190 break;
191 }
192
193 k_sleep(K_MSEC(WPA_SUPP_STATE_POLLING_MS));
194 }
195 out:
196 return ret;
197 }
198
supp_shell_connect_status(struct k_work * work)199 static void supp_shell_connect_status(struct k_work *work)
200 {
201 static int seconds_counter;
202 int status = CONNECTION_SUCCESS;
203 int conn_result = CONNECTION_FAILURE;
204 struct wpa_supplicant *wpa_s;
205 struct wpa_supp_api_ctrl *ctrl = &wpas_api_ctrl;
206
207 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
208
209 if (ctrl->status_thread_state == STATUS_THREAD_RUNNING && ctrl->terminate) {
210 status = CONNECTION_TERMINATED;
211 goto out;
212 }
213
214 wpa_s = get_wpa_s_handle(ctrl->dev);
215 if (!wpa_s) {
216 status = CONNECTION_FAILURE;
217 goto out;
218 }
219
220 if (ctrl->requested_op == CONNECT && wpa_s->wpa_state != WPA_COMPLETED) {
221 if (ctrl->connection_timeout > 0 &&
222 seconds_counter++ > ctrl->connection_timeout) {
223 if (!wpa_cli_cmd_v("disconnect")) {
224 goto out;
225 }
226
227 conn_result = -ETIMEDOUT;
228 supplicant_send_wifi_mgmt_event(wpa_s->ifname,
229 NET_EVENT_WIFI_CMD_CONNECT_RESULT,
230 (void *)&conn_result, sizeof(int));
231 status = CONNECTION_FAILURE;
232 goto out;
233 }
234
235 k_work_reschedule_for_queue(get_workq(), &wpa_supp_status_work,
236 K_SECONDS(OP_STATUS_POLLING_INTERVAL));
237 ctrl->status_thread_state = STATUS_THREAD_RUNNING;
238 k_mutex_unlock(&wpa_supplicant_mutex);
239 return;
240 }
241 out:
242 seconds_counter = 0;
243
244 ctrl->status_thread_state = STATUS_THREAD_STOPPED;
245 k_mutex_unlock(&wpa_supplicant_mutex);
246 }
247
get_mode_by_band(struct wpa_supplicant * wpa_s,uint8_t band)248 static struct hostapd_hw_modes *get_mode_by_band(struct wpa_supplicant *wpa_s, uint8_t band)
249 {
250 enum hostapd_hw_mode hw_mode;
251 bool is_6ghz = (band == WIFI_FREQ_BAND_6_GHZ) ? true : false;
252
253 if (band == WIFI_FREQ_BAND_2_4_GHZ) {
254 hw_mode = HOSTAPD_MODE_IEEE80211G;
255 } else if ((band == WIFI_FREQ_BAND_5_GHZ) ||
256 (band == WIFI_FREQ_BAND_6_GHZ)) {
257 hw_mode = HOSTAPD_MODE_IEEE80211A;
258 } else {
259 return NULL;
260 }
261
262 return get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, is_6ghz);
263 }
264
wpa_supp_supported_channels(struct wpa_supplicant * wpa_s,uint8_t band,char ** chan_list)265 static int wpa_supp_supported_channels(struct wpa_supplicant *wpa_s, uint8_t band, char **chan_list)
266 {
267 struct hostapd_hw_modes *mode = NULL;
268 int i;
269 int offset, retval;
270 int size;
271 char *_chan_list;
272
273 mode = get_mode_by_band(wpa_s, band);
274 if (!mode) {
275 wpa_printf(MSG_ERROR, "Unsupported or invalid band: %d", band);
276 return -EINVAL;
277 }
278
279 size = ((mode->num_channels) * CHAN_NUM_LEN) + 1;
280 _chan_list = os_malloc(size);
281 if (!_chan_list) {
282 wpa_printf(MSG_ERROR, "Mem alloc failed for channel list");
283 return -ENOMEM;
284 }
285
286 retval = 0;
287 offset = 0;
288 for (i = 0; i < mode->num_channels; i++) {
289 retval = snprintf(_chan_list + offset, CHAN_NUM_LEN, " %d",
290 mode->channels[i].freq);
291 offset += retval;
292 }
293 *chan_list = _chan_list;
294
295 return 0;
296 }
297
wpa_supp_band_chan_compat(struct wpa_supplicant * wpa_s,uint8_t band,uint8_t channel)298 static int wpa_supp_band_chan_compat(struct wpa_supplicant *wpa_s, uint8_t band, uint8_t channel)
299 {
300 struct hostapd_hw_modes *mode = NULL;
301 int i;
302
303 mode = get_mode_by_band(wpa_s, band);
304 if (!mode) {
305 wpa_printf(MSG_ERROR, "Unsupported or invalid band: %d", band);
306 return -EINVAL;
307 }
308
309 for (i = 0; i < mode->num_channels; i++) {
310 if (mode->channels[i].chan == channel) {
311 return mode->channels[i].freq;
312 }
313 }
314
315 wpa_printf(MSG_ERROR, "Channel %d not supported for band %d", channel, band);
316
317 return -EINVAL;
318 }
319
wpa_supp_restart_status_work(void)320 static inline void wpa_supp_restart_status_work(void)
321 {
322 /* Terminate synchronously */
323 wpas_api_ctrl.terminate = 1;
324 k_work_flush_delayable(&wpa_supp_status_work, &wpas_api_ctrl.sync);
325 wpas_api_ctrl.terminate = 0;
326
327 /* Start afresh */
328 k_work_reschedule_for_queue(get_workq(), &wpa_supp_status_work, K_MSEC(10));
329 }
330
chan_to_freq(int chan)331 static inline int chan_to_freq(int chan)
332 {
333 /* We use global channel list here and also use the widest
334 * op_class for 5GHz channels as there is no user input
335 * for these (yet).
336 */
337 int freq = -1;
338 int op_classes[] = {81, 82, 128};
339 int op_classes_size = ARRAY_SIZE(op_classes);
340
341 for (int i = 0; i < op_classes_size; i++) {
342 freq = ieee80211_chan_to_freq(NULL, op_classes[i], chan);
343 if (freq > 0) {
344 break;
345 }
346 }
347
348 if (freq <= 0) {
349 wpa_printf(MSG_ERROR, "Invalid channel %d", chan);
350 return -1;
351 }
352
353 return freq;
354 }
355
wpas_band_to_zephyr(enum wpa_radio_work_band band)356 static inline enum wifi_frequency_bands wpas_band_to_zephyr(enum wpa_radio_work_band band)
357 {
358 switch (band) {
359 case BAND_2_4_GHZ:
360 return WIFI_FREQ_BAND_2_4_GHZ;
361 case BAND_5_GHZ:
362 return WIFI_FREQ_BAND_5_GHZ;
363 default:
364 return WIFI_FREQ_BAND_UNKNOWN;
365 }
366 }
367
wpas_key_mgmt_to_zephyr_wpa3_ent(int key_mgmt)368 static inline enum wifi_wpa3_enterprise_type wpas_key_mgmt_to_zephyr_wpa3_ent(int key_mgmt)
369 {
370 switch (key_mgmt) {
371 case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
372 return WIFI_WPA3_ENTERPRISE_SUITEB;
373 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
374 return WIFI_WPA3_ENTERPRISE_SUITEB_192;
375 case WPA_KEY_MGMT_IEEE8021X_SHA256:
376 return WIFI_WPA3_ENTERPRISE_ONLY;
377 default:
378 return WIFI_WPA3_ENTERPRISE_NA;
379 }
380 }
381
wpas_key_mgmt_to_zephyr(bool is_hapd,void * config,int key_mgmt,int proto,int pwe)382 static inline enum wifi_security_type wpas_key_mgmt_to_zephyr(bool is_hapd,
383 void *config, int key_mgmt, int proto, int pwe)
384 {
385 switch (key_mgmt) {
386 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
387 case WPA_KEY_MGMT_IEEE8021X:
388 case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
389 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
390 case WPA_KEY_MGMT_IEEE8021X_SHA256:
391 if (is_hapd) {
392 #ifdef CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE
393 struct hostapd_bss_config *conf = (struct hostapd_bss_config *)config;
394
395 switch (conf->eap_user->methods[0].method) {
396 case WIFI_EAP_TYPE_PEAP:
397 if (conf->eap_user->next && conf->eap_user->next->phase2) {
398 switch (conf->eap_user->next->methods[0].method) {
399 case WIFI_EAP_TYPE_MSCHAPV2:
400 return WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2;
401 case WIFI_EAP_TYPE_GTC:
402 return WIFI_SECURITY_TYPE_EAP_PEAP_GTC;
403 case WIFI_EAP_TYPE_TLS:
404 return WIFI_SECURITY_TYPE_EAP_PEAP_TLS;
405 }
406 }
407 case WIFI_EAP_TYPE_TTLS:
408 if (conf->eap_user->next && conf->eap_user->next->phase2) {
409 if (conf->eap_user->next->ttls_auth & 0x1E) {
410 return WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2;
411 }
412 }
413 }
414 #endif
415 } else {
416 struct wpa_ssid *ssid = (struct wpa_ssid *)config;
417
418 switch (ssid->eap.eap_methods->method) {
419 case WIFI_EAP_TYPE_TTLS:
420 if (!os_memcmp(ssid->eap.phase2, "auth=MSCHAPV2",
421 os_strlen(ssid->eap.phase2))) {
422 return WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2;
423 }
424 case WIFI_EAP_TYPE_PEAP:
425 if (!os_memcmp(ssid->eap.phase2, "auth=MSCHAPV2",
426 os_strlen(ssid->eap.phase2))) {
427 return WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2;
428 } else if (!os_memcmp(ssid->eap.phase2, "auth=GTC",
429 os_strlen(ssid->eap.phase2))) {
430 return WIFI_SECURITY_TYPE_EAP_PEAP_GTC;
431 } else if (!os_memcmp(ssid->eap.phase2, "auth=TLS",
432 os_strlen(ssid->eap.phase2))) {
433 return WIFI_SECURITY_TYPE_EAP_PEAP_TLS;
434 }
435 }
436 }
437 return WIFI_SECURITY_TYPE_EAP_TLS;
438 #endif
439 case WPA_KEY_MGMT_NONE:
440 return WIFI_SECURITY_TYPE_NONE;
441 case WPA_KEY_MGMT_PSK:
442 if (proto == WPA_PROTO_RSN) {
443 return WIFI_SECURITY_TYPE_PSK;
444 } else {
445 return WIFI_SECURITY_TYPE_WPA_PSK;
446 }
447 case WPA_KEY_MGMT_PSK_SHA256:
448 return WIFI_SECURITY_TYPE_PSK_SHA256;
449 case WPA_KEY_MGMT_SAE:
450 if (pwe == 1) {
451 return WIFI_SECURITY_TYPE_SAE_H2E;
452 } else if (pwe == 2) {
453 return WIFI_SECURITY_TYPE_SAE_AUTO;
454 } else {
455 return WIFI_SECURITY_TYPE_SAE_HNP;
456 }
457 case WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK:
458 return WIFI_SECURITY_TYPE_WPA_AUTO_PERSONAL;
459 case WPA_KEY_MGMT_FT_PSK:
460 return WIFI_SECURITY_TYPE_FT_PSK;
461 case WPA_KEY_MGMT_FT_SAE:
462 return WIFI_SECURITY_TYPE_FT_SAE;
463 case WPA_KEY_MGMT_FT_IEEE8021X:
464 return WIFI_SECURITY_TYPE_FT_EAP;
465 case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
466 return WIFI_SECURITY_TYPE_FT_EAP_SHA384;
467 case WPA_KEY_MGMT_SAE_EXT_KEY:
468 return WIFI_SECURITY_TYPE_SAE_EXT_KEY;
469 default:
470 return WIFI_SECURITY_TYPE_UNKNOWN;
471 }
472 }
473
474 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
wpas_config_process_blob(struct wpa_config * config,char * name,uint8_t * data,uint32_t data_len)475 static int wpas_config_process_blob(struct wpa_config *config, char *name, uint8_t *data,
476 uint32_t data_len)
477 {
478 struct wpa_config_blob *blob;
479
480 if (!data || !data_len) {
481 return -1;
482 }
483
484 blob = os_zalloc(sizeof(*blob));
485 if (blob == NULL) {
486 return -1;
487 }
488
489 blob->data = os_zalloc(data_len);
490 if (blob->data == NULL) {
491 os_free(blob);
492 return -1;
493 }
494
495 blob->name = os_strdup(name);
496
497 if (blob->name == NULL) {
498 wpa_config_free_blob(blob);
499 return -1;
500 }
501
502 os_memcpy(blob->data, data, data_len);
503 blob->len = data_len;
504
505 wpa_config_set_blob(config, blob);
506
507 return 0;
508 }
509 #endif
510
511 #if defined CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE || \
512 defined CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE
supplicant_add_enterprise_creds(const struct device * dev,struct wifi_enterprise_creds_params * creds)513 int supplicant_add_enterprise_creds(const struct device *dev,
514 struct wifi_enterprise_creds_params *creds)
515 {
516 int ret = 0;
517
518 if (!creds) {
519 ret = -1;
520 wpa_printf(MSG_ERROR, "enterprise creds is NULL");
521 goto out;
522 }
523
524 memcpy((void *)&enterprise_creds, (void *)creds,
525 sizeof(struct wifi_enterprise_creds_params));
526
527 out:
528 return ret;
529 }
530
531 static const struct wifi_cipher_desc ciphers[] = {
532 {WPA_CAPA_ENC_GCMP_256, "GCMP-256"},
533 {WPA_CAPA_ENC_CCMP, "CCMP"},
534 {WPA_CAPA_ENC_GCMP, "GCMP"},
535 };
536
537 static const struct wifi_cipher_desc ciphers_group_mgmt[] = {
538 {WPA_CAPA_ENC_BIP, "AES-128-CMAC"},
539 {WPA_CAPA_ENC_BIP_GMAC_128, "BIP-GMAC-128"},
540 {WPA_CAPA_ENC_BIP_GMAC_256, "BIP-GMAC-256"},
541 };
542
543 static struct wifi_eap_config eap_config[] = {
544 {WIFI_SECURITY_TYPE_EAP_TLS, WIFI_EAP_TYPE_TLS, WIFI_EAP_TYPE_NONE, "TLS", NULL},
545 {WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2, WIFI_EAP_TYPE_PEAP, WIFI_EAP_TYPE_MSCHAPV2, "PEAP",
546 "auth=MSCHAPV2"},
547 {WIFI_SECURITY_TYPE_EAP_PEAP_GTC, WIFI_EAP_TYPE_PEAP, WIFI_EAP_TYPE_GTC, "PEAP",
548 "auth=GTC"},
549 {WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2, WIFI_EAP_TYPE_TTLS, WIFI_EAP_TYPE_NONE, "TTLS",
550 "auth=MSCHAPV2"},
551 {WIFI_SECURITY_TYPE_EAP_PEAP_TLS, WIFI_EAP_TYPE_PEAP, WIFI_EAP_TYPE_TLS, "PEAP",
552 "auth=TLS"},
553 };
554
process_cipher_config(struct wifi_connect_req_params * params,struct wifi_eap_cipher_config * cipher_config)555 int process_cipher_config(struct wifi_connect_req_params *params,
556 struct wifi_eap_cipher_config *cipher_config)
557 {
558 unsigned int cipher_capa;
559 unsigned int gropu_mgmt_cipher_capa;
560 unsigned int index;
561
562 if (params->wpa3_ent_mode == WIFI_WPA3_ENTERPRISE_SUITEB) {
563 cipher_capa = WPA_CAPA_ENC_GCMP;
564 gropu_mgmt_cipher_capa = WPA_CAPA_ENC_BIP_GMAC_128;
565 cipher_config->key_mgmt = "WPA-EAP-SUITE-B";
566 cipher_config->openssl_ciphers = "SUITEB128";
567 cipher_config->tls_flags = "[SUITEB]";
568 } else if (params->wpa3_ent_mode == WIFI_WPA3_ENTERPRISE_SUITEB_192) {
569 cipher_capa = WPA_CAPA_ENC_GCMP_256;
570 gropu_mgmt_cipher_capa = WPA_CAPA_ENC_BIP_GMAC_256;
571 if (params->ft_used) {
572 cipher_config->key_mgmt = "WPA-EAP-SUITE-B-192 FT-EAP-SHA384";
573 } else {
574 cipher_config->key_mgmt = "WPA-EAP-SUITE-B-192";
575 }
576 cipher_config->openssl_ciphers = "SUITEB192";
577 cipher_config->tls_flags = "[SUITEB]";
578 } else if (params->wpa3_ent_mode == WIFI_WPA3_ENTERPRISE_ONLY) {
579 cipher_capa = WPA_CAPA_ENC_CCMP;
580 gropu_mgmt_cipher_capa = WPA_CAPA_ENC_BIP;
581 cipher_config->key_mgmt = "WPA-EAP-SHA256";
582 } else {
583 cipher_capa = WPA_CAPA_ENC_CCMP;
584 gropu_mgmt_cipher_capa = WPA_CAPA_ENC_BIP;
585 if (params->ft_used) {
586 cipher_config->key_mgmt = "WPA-EAP FT-EAP";
587 } else {
588 cipher_config->key_mgmt = "WPA-EAP";
589 }
590 }
591
592 for (index = 0; index < ARRAY_SIZE(ciphers); index++) {
593 if (cipher_capa == ciphers[index].capa) {
594 cipher_config->group_cipher = ciphers[index].name;
595 cipher_config->pairwise_cipher = ciphers[index].name;
596 break;
597 }
598 }
599
600 if (index == ARRAY_SIZE(ciphers)) {
601 wpa_printf(MSG_ERROR, "Get ciphers error");
602 goto out;
603 }
604
605 for (index = 0; index < ARRAY_SIZE(ciphers_group_mgmt); index++) {
606 if (gropu_mgmt_cipher_capa == ciphers_group_mgmt[index].capa) {
607 cipher_config->group_mgmt_cipher = ciphers_group_mgmt[index].name;
608 break;
609 }
610 }
611
612 if (index == ARRAY_SIZE(ciphers_group_mgmt)) {
613 wpa_printf(MSG_ERROR, "Get group mgmt ciphers error");
614 goto out;
615 }
616
617 return 0;
618 out:
619 return -EINVAL;
620 }
621
is_eap_valid_security(int security)622 static int is_eap_valid_security(int security)
623 {
624 return (security == WIFI_SECURITY_TYPE_EAP_TLS ||
625 security == WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2 ||
626 security == WIFI_SECURITY_TYPE_EAP_PEAP_GTC ||
627 security == WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2 ||
628 security == WIFI_SECURITY_TYPE_EAP_PEAP_TLS);
629 }
630 #endif
631
632 #ifdef CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE
hapd_process_cert_data(struct hostapd_bss_config * conf,char * type,uint8_t * data,uint32_t data_len)633 static int hapd_process_cert_data(struct hostapd_bss_config *conf,
634 char *type, uint8_t *data, uint32_t data_len)
635 {
636 if (os_strcmp(type, "ca_cert_blob") == 0) {
637 conf->ca_cert_blob = data;
638 conf->ca_cert_blob_len = data_len;
639 } else if (os_strcmp(type, "server_cert_blob") == 0) {
640 conf->server_cert_blob = data;
641 conf->server_cert_blob_len = data_len;
642 } else if (os_strcmp(type, "private_key_blob") == 0) {
643 conf->private_key_blob = data;
644 conf->private_key_blob_len = data_len;
645 } else if (os_strcmp(type, "dh_blob") == 0) {
646 conf->dh_blob = data;
647 conf->dh_blob_len = data_len;
648 } else {
649 wpa_printf(MSG_ERROR, "input type error");
650 return -ENOTSUP;
651 }
652
653 return 0;
654 }
655
hapd_get_eap_config(struct wifi_connect_req_params * params,struct wifi_eap_config * eap_cfg)656 static int hapd_get_eap_config(struct wifi_connect_req_params *params,
657 struct wifi_eap_config *eap_cfg)
658 {
659 unsigned int index = 0;
660
661 for (index = 0; index < ARRAY_SIZE(eap_config); index++) {
662 if (params->security == eap_config[index].type) {
663 memcpy(eap_cfg, &eap_config[index], sizeof(struct wifi_eap_config));
664 break;
665 }
666 }
667
668 if (index == ARRAY_SIZE(eap_config)) {
669 wpa_printf(MSG_ERROR, "Get eap method type with security type: %d",
670 params->security);
671 return -ENOTSUP;
672 }
673
674 return 0;
675 }
676
hostapd_process_eap_user_phase1(struct wifi_connect_req_params * params,struct hostapd_eap_user ** pnew_user)677 static struct hostapd_eap_user *hostapd_process_eap_user_phase1(
678 struct wifi_connect_req_params *params, struct hostapd_eap_user **pnew_user)
679 {
680 struct hostapd_eap_user *user = NULL, *tail = NULL, *new_user = NULL;
681 struct wifi_eap_config eap_cfg;
682
683 user = os_zalloc(sizeof(*user));
684 if (user == NULL) {
685 wpa_printf(MSG_ERROR, "EAP user allocation failed");
686 goto failed;
687 }
688
689 user->force_version = -1;
690 if (params->eap_ver >= 0) {
691 user->force_version = params->eap_ver;
692 }
693
694 if (hapd_get_eap_config(params, &eap_cfg)) {
695 goto failed;
696 }
697
698 user->methods[0].method = eap_cfg.eap_type_phase1;
699 user->methods[0].vendor = 0;
700
701 if (tail == NULL) {
702 tail = new_user = user;
703 } else {
704 tail->next = user;
705 tail = user;
706 }
707
708 *pnew_user = new_user;
709
710 return tail;
711
712 failed:
713 if (user) {
714 hostapd_config_free_eap_user(user);
715 }
716
717 return NULL;
718 }
719
hostapd_process_eap_user(struct wifi_connect_req_params * params,struct hostapd_bss_config * conf)720 static int hostapd_process_eap_user(struct wifi_connect_req_params *params,
721 struct hostapd_bss_config *conf)
722 {
723 struct hostapd_eap_user *user = NULL, *tail = NULL, *user_list = NULL;
724 int i, nusers = params->nusers;
725 const char *identity, *password;
726 struct wifi_eap_config eap_cfg;
727 int ret = 0;
728
729 if (hapd_get_eap_config(params, &eap_cfg)) {
730 goto failed;
731 }
732
733 if (eap_cfg.phase2 != NULL) {
734 tail = hostapd_process_eap_user_phase1(params, &user_list);
735 }
736
737 if (eap_cfg.phase2 != NULL && !nusers) {
738 wpa_printf(MSG_ERROR, "EAP users not found.");
739 goto failed;
740 }
741
742 for (i = 0; i < nusers; i++) {
743 user = os_zalloc(sizeof(*user));
744 if (user == NULL) {
745 wpa_printf(MSG_ERROR, "EAP user allocation failed");
746 goto failed;
747 }
748
749 user->force_version = -1;
750 if (params->eap_ver >= 0) {
751 user->force_version = params->eap_ver;
752 }
753
754 identity = params->identities[i];
755 password = params->passwords[i];
756
757 user->identity = os_memdup(identity, os_strlen(identity));
758 if (user->identity == NULL) {
759 wpa_printf(MSG_ERROR,
760 "Failed to allocate "
761 "memory for EAP identity");
762 goto failed;
763 }
764 user->identity_len = os_strlen(identity);
765
766 user->methods[0].method = eap_cfg.eap_type_phase1;
767 user->methods[0].vendor = 0;
768
769 if (eap_cfg.phase2 != NULL) {
770 user->methods[0].method = eap_cfg.eap_type_phase2;
771 user->password = os_memdup(password, os_strlen(password));
772 if (user->password == NULL) {
773 wpa_printf(MSG_ERROR,
774 "Failed to allocate "
775 "memory for EAP password");
776 goto failed;
777 }
778 user->password_len = os_strlen(password);
779
780 user->phase2 = 1;
781 }
782
783 if (params->security == WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2) {
784 user->ttls_auth |= 0x1E;
785 }
786
787 if (tail == NULL) {
788 tail = user_list = user;
789 } else {
790 tail->next = user;
791 tail = user;
792 }
793
794 continue;
795
796 failed:
797 if (user) {
798 hostapd_config_free_eap_user(user);
799 }
800
801 ret = -1;
802 break;
803 }
804
805 if (ret == 0) {
806 hostapd_config_free_eap_users(conf->eap_user);
807 conf->eap_user = user_list;
808 } else {
809 hostapd_config_free_eap_users(user_list);
810 }
811
812 return ret;
813 }
814
hapd_process_enterprise_config(struct hostapd_iface * iface,struct wifi_connect_req_params * params)815 int hapd_process_enterprise_config(struct hostapd_iface *iface,
816 struct wifi_connect_req_params *params)
817 {
818 struct wifi_eap_cipher_config cipher_config = {
819 NULL, "DEFAULT:!EXP:!LOW", "CCMP", "CCMP", "AES-128-CMAC", NULL};
820 int ret = 0;
821
822 if (process_cipher_config(params, &cipher_config)) {
823 goto out;
824 }
825
826 if (!hostapd_cli_cmd_v("set wpa %d", WPA_PROTO_RSN)) {
827 goto out;
828 }
829
830 if (!hostapd_cli_cmd_v("set wpa_key_mgmt %s", cipher_config.key_mgmt)) {
831 goto out;
832 }
833
834 if (!hostapd_cli_cmd_v("set rsn_pairwise %s", cipher_config.pairwise_cipher)) {
835 goto out;
836 }
837
838 if (!hostapd_cli_cmd_v("set wpa_pairwise %s", cipher_config.pairwise_cipher)) {
839 goto out;
840 }
841
842 if (!hostapd_cli_cmd_v("set group_cipher %s", cipher_config.group_cipher)) {
843 goto out;
844 }
845
846 if (!hostapd_cli_cmd_v("set group_mgmt_cipher %s", cipher_config.group_mgmt_cipher)) {
847 goto out;
848 }
849
850 if (cipher_config.tls_flags != NULL) {
851 if (!hostapd_cli_cmd_v("set tls_flags %s", cipher_config.tls_flags)) {
852 goto out;
853 }
854 }
855
856 if (!hostapd_cli_cmd_v("set ieee8021x %d", 1)) {
857 goto out;
858 }
859
860 if (!hostapd_cli_cmd_v("set eapol_version %d", 2)) {
861 goto out;
862 }
863
864 if (!hostapd_cli_cmd_v("set eap_server %d", 1)) {
865 goto out;
866 }
867
868 if (hapd_process_cert_data(iface->bss[0]->conf, "ca_cert_blob",
869 enterprise_creds.ca_cert, enterprise_creds.ca_cert_len)) {
870 goto out;
871 }
872
873 if (hapd_process_cert_data(iface->bss[0]->conf, "server_cert_blob",
874 enterprise_creds.server_cert, enterprise_creds.server_cert_len)) {
875 goto out;
876 }
877
878 if (hapd_process_cert_data(iface->bss[0]->conf, "private_key_blob",
879 enterprise_creds.server_key, enterprise_creds.server_key_len)) {
880 goto out;
881 }
882
883 if (hapd_process_cert_data(iface->bss[0]->conf, "dh_blob",
884 enterprise_creds.dh_param, enterprise_creds.dh_param_len)) {
885 goto out;
886 }
887
888 if (!hostapd_cli_cmd_v("set private_key_passwd %s", params->key_passwd)) {
889 goto out;
890 }
891
892 if (hostapd_process_eap_user(params, iface->bss[0]->conf)) {
893 goto out;
894 }
895
896 return ret;
897 out:
898 return -1;
899 }
900 #endif
901
902 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
wpas_remove_certs(struct wpa_supplicant * wpa_s)903 static void wpas_remove_certs(struct wpa_supplicant *wpa_s)
904 {
905 wpa_config_remove_blob(wpa_s->conf, "ca_cert");
906 wpa_config_remove_blob(wpa_s->conf, "client_cert");
907 wpa_config_remove_blob(wpa_s->conf, "private_key");
908 wpa_config_remove_blob(wpa_s->conf, "ca_cert2");
909 wpa_config_remove_blob(wpa_s->conf, "client_cert2");
910 wpa_config_remove_blob(wpa_s->conf, "private_key2");
911 }
912 #endif
913
wpas_add_and_config_network(struct wpa_supplicant * wpa_s,struct wifi_connect_req_params * params,bool mode_ap)914 static int wpas_add_and_config_network(struct wpa_supplicant *wpa_s,
915 struct wifi_connect_req_params *params,
916 bool mode_ap)
917 {
918 struct add_network_resp resp = {0};
919 char *chan_list = NULL;
920 struct net_eth_addr mac = {0};
921 int ret = 0;
922 uint8_t ssid_null_terminated[WIFI_SSID_MAX_LEN + 1];
923 uint8_t psk_null_terminated[WIFI_PSK_MAX_LEN + 1];
924 uint8_t sae_null_terminated[WIFI_SAE_PSWD_MAX_LEN + 1];
925 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
926 struct wifi_eap_cipher_config cipher_config = {NULL, "DEFAULT:!EXP:!LOW", "CCMP",
927 "CCMP", "AES-128-CMAC", NULL};
928 char *method = NULL;
929 char phase1[128] = {0};
930 char *phase2 = NULL;
931 unsigned int index;
932
933 wpas_remove_certs(wpa_s);
934 #endif
935
936 if (!wpa_cli_cmd_v("remove_network all")) {
937 goto out;
938 }
939
940 ret = z_wpa_ctrl_add_network(&resp);
941 if (ret) {
942 wpa_printf(MSG_ERROR, "Failed to add network");
943 goto out;
944 }
945
946 wpa_printf(MSG_DEBUG, "NET added: %d", resp.network_id);
947
948 if (mode_ap) {
949 if (!wpa_cli_cmd_v("set_network %d mode 2", resp.network_id)) {
950 goto out;
951 }
952 }
953
954 if (params->ssid_length > WIFI_SSID_MAX_LEN) {
955 wpa_printf(MSG_ERROR, "SSID too long (max %d characters)", WIFI_SSID_MAX_LEN);
956 goto out;
957 }
958
959 strncpy(ssid_null_terminated, params->ssid, WIFI_SSID_MAX_LEN);
960 ssid_null_terminated[params->ssid_length] = '\0';
961
962 if (!wpa_cli_cmd_v("set_network %d ssid \"%s\"",
963 resp.network_id, ssid_null_terminated)) {
964 goto out;
965 }
966
967 if (!wpa_cli_cmd_v("set_network %d scan_ssid 1", resp.network_id)) {
968 goto out;
969 }
970
971 if (!wpa_cli_cmd_v("set_network %d key_mgmt NONE", resp.network_id)) {
972 goto out;
973 }
974
975 if (!wpa_cli_cmd_v("set_network %d ieee80211w 0", resp.network_id)) {
976 goto out;
977 }
978
979 if (params->band != WIFI_FREQ_BAND_UNKNOWN) {
980 ret = wpa_supp_supported_channels(wpa_s, params->band, &chan_list);
981 if (ret < 0) {
982 goto rem_net;
983 }
984
985 if (chan_list) {
986 if (!wpa_cli_cmd_v("set_network %d scan_freq%s", resp.network_id,
987 chan_list)) {
988 os_free(chan_list);
989 goto out;
990 }
991
992 os_free(chan_list);
993 }
994 }
995
996 if (params->security != WIFI_SECURITY_TYPE_NONE) {
997 if (params->psk) {
998 if ((params->psk_length < WIFI_PSK_MIN_LEN) ||
999 (params->psk_length > WIFI_PSK_MAX_LEN)) {
1000 wpa_printf(MSG_ERROR,
1001 "Passphrase should be in range (%d-%d) characters",
1002 WIFI_PSK_MIN_LEN, WIFI_PSK_MAX_LEN);
1003 goto out;
1004 }
1005 strncpy(psk_null_terminated, params->psk, WIFI_PSK_MAX_LEN);
1006 psk_null_terminated[params->psk_length] = '\0';
1007 }
1008
1009 /* SAP - only open and WPA2-PSK are supported for now */
1010 if (mode_ap && params->security != WIFI_SECURITY_TYPE_PSK) {
1011 ret = -1;
1012 wpa_printf(MSG_ERROR, "Unsupported security type: %d",
1013 params->security);
1014 goto rem_net;
1015 }
1016
1017 /* Except for WPA-PSK, rest all are under WPA2 */
1018 if (params->security != WIFI_SECURITY_TYPE_WPA_PSK) {
1019 if (!wpa_cli_cmd_v("set_network %d proto RSN",
1020 resp.network_id)) {
1021 goto out;
1022 }
1023 }
1024
1025 if (params->security == WIFI_SECURITY_TYPE_SAE_HNP ||
1026 params->security == WIFI_SECURITY_TYPE_SAE_H2E ||
1027 params->security == WIFI_SECURITY_TYPE_SAE_AUTO ||
1028 params->security == WIFI_SECURITY_TYPE_SAE_EXT_KEY) {
1029 if (params->sae_password) {
1030 if ((params->sae_password_length < WIFI_PSK_MIN_LEN) ||
1031 (params->sae_password_length > WIFI_SAE_PSWD_MAX_LEN)) {
1032 wpa_printf(MSG_ERROR,
1033 "Passphrase should be in range (%d-%d) characters",
1034 WIFI_PSK_MIN_LEN, WIFI_SAE_PSWD_MAX_LEN);
1035 goto out;
1036 }
1037 strncpy(sae_null_terminated, params->sae_password,
1038 WIFI_SAE_PSWD_MAX_LEN);
1039 sae_null_terminated[params->sae_password_length] = '\0';
1040 if (!wpa_cli_cmd_v("set_network %d sae_password \"%s\"",
1041 resp.network_id, sae_null_terminated)) {
1042 goto out;
1043 }
1044 } else {
1045 if (!wpa_cli_cmd_v("set_network %d sae_password \"%s\"",
1046 resp.network_id, psk_null_terminated)) {
1047 goto out;
1048 }
1049 }
1050
1051 if (!wpa_cli_cmd_v("set sae_pwe %d",
1052 (params->security == WIFI_SECURITY_TYPE_SAE_H2E)
1053 ? 1
1054 : ((params->security == WIFI_SECURITY_TYPE_SAE_HNP)
1055 ? 0
1056 : 2))) {
1057 goto out;
1058 }
1059
1060 if (params->security != WIFI_SECURITY_TYPE_SAE_EXT_KEY) {
1061 if (!wpa_cli_cmd_v("set_network %d key_mgmt SAE%s", resp.network_id,
1062 params->ft_used ? " FT-SAE" : "")) {
1063 goto out;
1064 }
1065 } else {
1066 if (!wpa_cli_cmd_v("set_network %d key_mgmt SAE-EXT-KEY%s",
1067 resp.network_id,
1068 params->ft_used ? " FT-SAE-EXT-KEY" : "")) {
1069 goto out;
1070 }
1071 }
1072 } else if (params->security == WIFI_SECURITY_TYPE_PSK_SHA256) {
1073 if (!wpa_cli_cmd_v("set_network %d psk \"%s\"",
1074 resp.network_id, psk_null_terminated)) {
1075 goto out;
1076 }
1077
1078 if (!wpa_cli_cmd_v("set_network %d key_mgmt WPA-PSK-SHA256",
1079 resp.network_id)) {
1080 goto out;
1081 }
1082 } else if (params->security == WIFI_SECURITY_TYPE_PSK ||
1083 params->security == WIFI_SECURITY_TYPE_WPA_PSK) {
1084 if (!wpa_cli_cmd_v("set_network %d psk \"%s\"",
1085 resp.network_id, psk_null_terminated)) {
1086 goto out;
1087 }
1088
1089 if (!wpa_cli_cmd_v("set_network %d key_mgmt WPA-PSK%s",
1090 resp.network_id, params->ft_used ? " FT-PSK" : "")) {
1091 goto out;
1092 }
1093
1094 if (params->security == WIFI_SECURITY_TYPE_WPA_PSK) {
1095 if (!wpa_cli_cmd_v("set_network %d proto WPA",
1096 resp.network_id)) {
1097 goto out;
1098 }
1099 }
1100 } else if (params->security == WIFI_SECURITY_TYPE_WPA_AUTO_PERSONAL) {
1101 if (!wpa_cli_cmd_v("set_network %d psk \"%s\"", resp.network_id,
1102 psk_null_terminated)) {
1103 goto out;
1104 }
1105
1106 if (params->sae_password) {
1107 if (!wpa_cli_cmd_v("set_network %d sae_password \"%s\"",
1108 resp.network_id, sae_null_terminated)) {
1109 goto out;
1110 }
1111 } else {
1112 if (!wpa_cli_cmd_v("set_network %d sae_password \"%s\"",
1113 resp.network_id, psk_null_terminated)) {
1114 goto out;
1115 }
1116 }
1117
1118 if (!wpa_cli_cmd_v("set sae_pwe 2")) {
1119 goto out;
1120 }
1121
1122 if (!wpa_cli_cmd_v("set_network %d key_mgmt WPA-PSK SAE",
1123 resp.network_id)) {
1124 goto out;
1125 }
1126 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
1127 } else if (is_eap_valid_security(params->security)) {
1128 if (process_cipher_config(params, &cipher_config)) {
1129 goto out;
1130 }
1131
1132 for (index = 0; index < ARRAY_SIZE(eap_config); index++) {
1133 if (params->security == eap_config[index].type) {
1134 method = eap_config[index].method;
1135 phase2 = eap_config[index].phase2;
1136 break;
1137 }
1138 }
1139
1140 if (index == ARRAY_SIZE(eap_config)) {
1141 wpa_printf(MSG_ERROR, "Get eap method error with security type: %d",
1142 params->security);
1143 goto out;
1144 }
1145
1146 if (params->wpa3_ent_mode == WIFI_WPA3_ENTERPRISE_SUITEB_192) {
1147 if (params->TLS_cipher == WIFI_EAP_TLS_ECC_P384) {
1148 if (!wpa_cli_cmd_v("set_network %d openssl_ciphers \"%s\"",
1149 resp.network_id,
1150 cipher_config.openssl_ciphers))
1151 goto out;
1152 } else if (params->TLS_cipher == WIFI_EAP_TLS_RSA_3K) {
1153 snprintf(phase1, sizeof(phase1), "tls_suiteb=1");
1154 if (!wpa_cli_cmd_v("set_network %d phase1 \"%s\"",
1155 resp.network_id, &phase1[0]))
1156 goto out;
1157 }
1158 }
1159
1160 if (!wpa_cli_cmd_v("set_network %d key_mgmt %s", resp.network_id,
1161 cipher_config.key_mgmt)) {
1162 goto out;
1163 }
1164
1165 if (!wpa_cli_cmd_v("set openssl_ciphers \"%s\"",
1166 cipher_config.openssl_ciphers)) {
1167 goto out;
1168 }
1169
1170 if (!wpa_cli_cmd_v("set_network %d group %s", resp.network_id,
1171 cipher_config.group_cipher)) {
1172 goto out;
1173 }
1174
1175 if (!wpa_cli_cmd_v("set_network %d pairwise %s", resp.network_id,
1176 cipher_config.pairwise_cipher)) {
1177 goto out;
1178 }
1179
1180 if (!wpa_cli_cmd_v("set_network %d group_mgmt %s", resp.network_id,
1181 cipher_config.group_mgmt_cipher)) {
1182 goto out;
1183 }
1184
1185 if (!wpa_cli_cmd_v("set_network %d proto RSN",
1186 resp.network_id)) {
1187 goto out;
1188 }
1189
1190 if (method != NULL) {
1191 if (!wpa_cli_cmd_v("set_network %d eap %s", resp.network_id,
1192 method)) {
1193 goto out;
1194 }
1195 }
1196
1197 if (params->security == WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2 ||
1198 params->security == WIFI_SECURITY_TYPE_EAP_PEAP_GTC ||
1199 params->security == WIFI_SECURITY_TYPE_EAP_PEAP_TLS) {
1200 snprintk(phase1, sizeof(phase1),
1201 "peapver=%d peaplabel=0 crypto_binding=0",
1202 params->eap_ver);
1203
1204 if (!wpa_cli_cmd_v("set_network %d phase1 \"%s\"", resp.network_id,
1205 &phase1[0])) {
1206 goto out;
1207 }
1208 }
1209
1210 if (phase2 != NULL) {
1211 if (!wpa_cli_cmd_v("set_network %d phase2 \"%s\"", resp.network_id,
1212 phase2)) {
1213 goto out;
1214 }
1215 }
1216
1217 if (params->eap_id_length > 0) {
1218 if (!wpa_cli_cmd_v("set_network %d identity \"%s\"",
1219 resp.network_id, params->eap_identity)) {
1220 goto out;
1221 }
1222 }
1223
1224 if (params->eap_passwd_length > 0) {
1225 if (!wpa_cli_cmd_v("set_network %d password \"%s\"",
1226 resp.network_id, params->eap_password)) {
1227 goto out;
1228 }
1229 }
1230
1231 if (!wpa_cli_cmd_v("set_network %d anonymous_identity \"%s\"",
1232 resp.network_id, params->anon_id)) {
1233 goto out;
1234 }
1235
1236 if (false == ((params->security == WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2 ||
1237 params->security == WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2) &&
1238 (!params->verify_peer_cert))) {
1239 if (wpas_config_process_blob(wpa_s->conf, "ca_cert",
1240 enterprise_creds.ca_cert,
1241 enterprise_creds.ca_cert_len)) {
1242 goto out;
1243 }
1244
1245 if (!wpa_cli_cmd_v("set_network %d ca_cert \"blob://ca_cert\"",
1246 resp.network_id)) {
1247 goto out;
1248 }
1249 }
1250
1251 if (wpas_config_process_blob(wpa_s->conf, "client_cert",
1252 enterprise_creds.client_cert,
1253 enterprise_creds.client_cert_len)) {
1254 goto out;
1255 }
1256
1257 if (!wpa_cli_cmd_v("set_network %d client_cert \"blob://client_cert\"",
1258 resp.network_id)) {
1259 goto out;
1260 }
1261
1262 if (wpas_config_process_blob(wpa_s->conf, "private_key",
1263 enterprise_creds.client_key,
1264 enterprise_creds.client_key_len)) {
1265 goto out;
1266 }
1267
1268 if (!wpa_cli_cmd_v("set_network %d private_key \"blob://private_key\"",
1269 resp.network_id)) {
1270 goto out;
1271 }
1272
1273 if (!wpa_cli_cmd_v("set_network %d private_key_passwd \"%s\"",
1274 resp.network_id, params->key_passwd)) {
1275 goto out;
1276 }
1277
1278 if (wpas_config_process_blob(wpa_s->conf, "ca_cert2",
1279 enterprise_creds.ca_cert2,
1280 enterprise_creds.ca_cert2_len)) {
1281 goto out;
1282 }
1283
1284 if (!wpa_cli_cmd_v("set_network %d ca_cert2 \"blob://ca_cert2\"",
1285 resp.network_id)) {
1286 goto out;
1287 }
1288
1289 if (wpas_config_process_blob(wpa_s->conf, "client_cert2",
1290 enterprise_creds.client_cert2,
1291 enterprise_creds.client_cert2_len)) {
1292 goto out;
1293 }
1294
1295 if (!wpa_cli_cmd_v("set_network %d client_cert2 \"blob://client_cert2\"",
1296 resp.network_id)) {
1297 goto out;
1298 }
1299
1300 if (wpas_config_process_blob(wpa_s->conf, "private_key2",
1301 enterprise_creds.client_key2,
1302 enterprise_creds.client_key2_len)) {
1303 goto out;
1304 }
1305
1306 if (!wpa_cli_cmd_v("set_network %d private_key2 \"blob://private_key2\"",
1307 resp.network_id)) {
1308 goto out;
1309 }
1310
1311 if (!wpa_cli_cmd_v("set_network %d private_key2_passwd \"%s\"",
1312 resp.network_id, params->key2_passwd)) {
1313 goto out;
1314 }
1315 #endif
1316 } else {
1317 ret = -1;
1318 wpa_printf(MSG_ERROR, "Unsupported security type: %d",
1319 params->security);
1320 goto rem_net;
1321 }
1322
1323 if (params->mfp) {
1324 if (!wpa_cli_cmd_v("set_network %d ieee80211w %d",
1325 resp.network_id, params->mfp)) {
1326 goto out;
1327 }
1328 }
1329 }
1330
1331 if (params->channel != WIFI_CHANNEL_ANY) {
1332 int freq;
1333
1334 if (params->band != WIFI_FREQ_BAND_UNKNOWN) {
1335 freq = wpa_supp_band_chan_compat(wpa_s, params->band, params->channel);
1336 if (freq < 0) {
1337 goto rem_net;
1338 }
1339 } else {
1340 freq = chan_to_freq(params->channel);
1341 if (freq < 0) {
1342 ret = -1;
1343 wpa_printf(MSG_ERROR, "Invalid channel %d",
1344 params->channel);
1345 goto rem_net;
1346 }
1347 }
1348
1349 if (mode_ap) {
1350 if (!wpa_cli_cmd_v("set_network %d frequency %d",
1351 resp.network_id, freq)) {
1352 goto out;
1353 }
1354 } else {
1355 if (!wpa_cli_cmd_v("set_network %d scan_freq %d",
1356 resp.network_id, freq)) {
1357 goto out;
1358 }
1359 }
1360 }
1361
1362 memcpy((void *)&mac, params->bssid, WIFI_MAC_ADDR_LEN);
1363 if (net_eth_is_addr_broadcast(&mac) ||
1364 net_eth_is_addr_multicast(&mac)) {
1365 wpa_printf(MSG_ERROR, "Invalid BSSID. Configuration "
1366 "of multicast or broadcast MAC is not allowed.");
1367 ret = -EINVAL;
1368 goto rem_net;
1369 }
1370
1371 if (!net_eth_is_addr_unspecified(&mac)) {
1372 char bssid_str[MAC_STR_LEN] = {0};
1373
1374 snprintf(bssid_str, MAC_STR_LEN, "%02x:%02x:%02x:%02x:%02x:%02x",
1375 params->bssid[0], params->bssid[1], params->bssid[2],
1376 params->bssid[3], params->bssid[4], params->bssid[5]);
1377
1378 if (!wpa_cli_cmd_v("set_network %d bssid %s",
1379 resp.network_id, bssid_str)) {
1380 goto out;
1381 }
1382 }
1383
1384 /* enable and select network */
1385 if (!wpa_cli_cmd_v("enable_network %d", resp.network_id)) {
1386 goto out;
1387 }
1388
1389 if (!wpa_cli_cmd_v("select_network %d", resp.network_id)) {
1390 goto out;
1391 }
1392
1393 memset(&last_wifi_conn_params, 0, sizeof(struct wifi_connect_req_params));
1394 memcpy((void *)&last_wifi_conn_params, params, sizeof(struct wifi_connect_req_params));
1395 return 0;
1396
1397 rem_net:
1398 if (!wpa_cli_cmd_v("remove_network %d", resp.network_id)) {
1399 goto out;
1400 }
1401
1402 out:
1403 return ret;
1404 }
1405
wpas_disconnect_network(const struct device * dev,int cur_mode)1406 static int wpas_disconnect_network(const struct device *dev, int cur_mode)
1407 {
1408 struct net_if *iface = net_if_lookup_by_dev(dev);
1409 struct wpa_supplicant *wpa_s;
1410 bool is_ap = false;
1411 int ret = 0;
1412
1413 if (!iface) {
1414 ret = -ENOENT;
1415 wpa_printf(MSG_ERROR, "Interface for device %s not found", dev->name);
1416 return ret;
1417 }
1418
1419 wpa_s = get_wpa_s_handle(dev);
1420 if (!wpa_s) {
1421 ret = -1;
1422 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
1423 goto out;
1424 }
1425
1426 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1427
1428 if (wpa_s->current_ssid && wpa_s->current_ssid->mode != cur_mode) {
1429 ret = -EBUSY;
1430 wpa_printf(MSG_ERROR, "Interface %s is not in %s mode", dev->name,
1431 cur_mode == WPAS_MODE_INFRA ? "STA" : "AP");
1432 goto out;
1433 }
1434
1435 is_ap = (cur_mode == WPAS_MODE_AP);
1436
1437 wpas_api_ctrl.dev = dev;
1438 wpas_api_ctrl.requested_op = DISCONNECT;
1439
1440 if (!wpa_cli_cmd_v("disconnect")) {
1441 goto out;
1442 }
1443
1444 out:
1445 k_mutex_unlock(&wpa_supplicant_mutex);
1446
1447 if (ret) {
1448 wpa_printf(MSG_ERROR, "Disconnect failed: %s", strerror(-ret));
1449 return ret;
1450 }
1451
1452 wpa_supp_restart_status_work();
1453
1454 ret = wait_for_disconnect_complete(dev);
1455 #ifdef CONFIG_AP
1456 if (is_ap) {
1457 supplicant_send_wifi_mgmt_ap_status(wpa_s,
1458 NET_EVENT_WIFI_CMD_AP_DISABLE_RESULT,
1459 ret == 0 ? WIFI_STATUS_AP_SUCCESS : WIFI_STATUS_AP_FAIL);
1460 } else {
1461 #else
1462 {
1463 #endif /* CONFIG_AP */
1464 wifi_mgmt_raise_disconnect_complete_event(iface, ret);
1465 }
1466
1467 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
1468 wpas_remove_certs(wpa_s);
1469 #endif
1470
1471 if (!wpa_cli_cmd_v("remove_network all")) {
1472 wpa_printf(MSG_ERROR, "Failed to remove all networks");
1473 }
1474
1475 return ret;
1476 }
1477
1478 /* Public API */
1479 int supplicant_connect(const struct device *dev, struct wifi_connect_req_params *params)
1480 {
1481 struct wpa_supplicant *wpa_s;
1482 int ret = 0;
1483
1484 if (!net_if_is_admin_up(net_if_lookup_by_dev(dev))) {
1485 wpa_printf(MSG_ERROR,
1486 "Interface %s is down, dropping connect",
1487 dev->name);
1488 return -1;
1489 }
1490
1491 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1492
1493 wpa_s = get_wpa_s_handle(dev);
1494 if (!wpa_s) {
1495 ret = -1;
1496 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
1497 goto out;
1498 }
1499
1500 /* Allow connect in STA mode only even if we are connected already */
1501 if (wpa_s->current_ssid && wpa_s->current_ssid->mode != WPAS_MODE_INFRA) {
1502 ret = -EBUSY;
1503 wpa_printf(MSG_ERROR, "Interface %s is not in STA mode", dev->name);
1504 goto out;
1505 }
1506
1507 ret = wpas_add_and_config_network(wpa_s, params, false);
1508 if (ret) {
1509 wpa_printf(MSG_ERROR, "Failed to add and configure network for STA mode: %d", ret);
1510 goto out;
1511 }
1512
1513 wpas_api_ctrl.dev = dev;
1514 wpas_api_ctrl.requested_op = CONNECT;
1515 wpas_api_ctrl.connection_timeout = params->timeout;
1516
1517 out:
1518 k_mutex_unlock(&wpa_supplicant_mutex);
1519
1520 if (!ret) {
1521 wpa_supp_restart_status_work();
1522 }
1523
1524 return ret;
1525 }
1526
1527 int supplicant_disconnect(const struct device *dev)
1528 {
1529 return wpas_disconnect_network(dev, WPAS_MODE_INFRA);
1530 }
1531
1532 static enum wifi_mfp_options get_mfp(enum mfp_options supp_mfp_option)
1533 {
1534 switch (supp_mfp_option) {
1535 case NO_MGMT_FRAME_PROTECTION:
1536 return WIFI_MFP_DISABLE;
1537 case MGMT_FRAME_PROTECTION_OPTIONAL:
1538 return WIFI_MFP_OPTIONAL;
1539 case MGMT_FRAME_PROTECTION_REQUIRED:
1540 return WIFI_MFP_REQUIRED;
1541 default:
1542 wpa_printf(MSG_ERROR, "Invalid mfp mapping %d", supp_mfp_option);
1543 break;
1544 }
1545
1546 return WIFI_MFP_DISABLE;
1547 }
1548
1549 static enum wifi_iface_mode get_iface_mode(enum wpas_mode supp_mode)
1550 {
1551 switch (supp_mode) {
1552 case WPAS_MODE_INFRA:
1553 return WIFI_MODE_INFRA;
1554 case WPAS_MODE_IBSS:
1555 return WIFI_MODE_IBSS;
1556 case WPAS_MODE_AP:
1557 return WIFI_MODE_AP;
1558 case WPAS_MODE_P2P_GO:
1559 return WIFI_MODE_P2P_GO;
1560 case WPAS_MODE_P2P_GROUP_FORMATION:
1561 return WIFI_MODE_P2P_GROUP_FORMATION;
1562 case WPAS_MODE_MESH:
1563 return WIFI_MODE_MESH;
1564 default:
1565 break;
1566 }
1567
1568 return WIFI_MODE_UNKNOWN;
1569 }
1570
1571 int supplicant_status(const struct device *dev, struct wifi_iface_status *status)
1572 {
1573 struct net_if *iface = net_if_lookup_by_dev(dev);
1574 struct wpa_supplicant *wpa_s;
1575 int ret = -1;
1576 struct wpa_signal_info *si = NULL;
1577 struct wpa_conn_info *conn_info = NULL;
1578
1579 if (!iface) {
1580 ret = -ENOENT;
1581 wpa_printf(MSG_ERROR, "Interface for device %s not found", dev->name);
1582 return ret;
1583 }
1584
1585 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1586
1587 wpa_s = get_wpa_s_handle(dev);
1588 if (!wpa_s) {
1589 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
1590 goto out;
1591 }
1592
1593 si = os_zalloc(sizeof(struct wpa_signal_info));
1594 if (!si) {
1595 wpa_printf(MSG_ERROR, "Failed to allocate memory for signal info");
1596 goto out;
1597 }
1598
1599 status->state = wpa_s->wpa_state; /* 1-1 Mapping */
1600
1601 if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
1602 struct wpa_ssid *ssid = wpa_s->current_ssid;
1603 u8 channel;
1604 struct signal_poll_resp signal_poll;
1605 u8 *_ssid = ssid->ssid;
1606 size_t ssid_len = ssid->ssid_len;
1607 struct status_resp cli_status;
1608 int proto;
1609 int key_mgmt;
1610 int sae_pwe;
1611
1612 if (!ssid) {
1613 wpa_printf(MSG_ERROR, "Failed to get current ssid");
1614 goto out;
1615 }
1616
1617 proto = ssid->proto;
1618 key_mgmt = ssid->key_mgmt;
1619 sae_pwe = wpa_s->conf->sae_pwe;
1620 os_memcpy(status->bssid, wpa_s->bssid, WIFI_MAC_ADDR_LEN);
1621 status->band = wpas_band_to_zephyr(wpas_freq_to_band(wpa_s->assoc_freq));
1622 status->wpa3_ent_type = wpas_key_mgmt_to_zephyr_wpa3_ent(key_mgmt);
1623 status->security = wpas_key_mgmt_to_zephyr(0, ssid, key_mgmt, proto, sae_pwe);
1624 status->mfp = get_mfp(ssid->ieee80211w);
1625 ieee80211_freq_to_chan(wpa_s->assoc_freq, &channel);
1626 status->channel = channel;
1627
1628 if (ssid_len == 0) {
1629 int _res = z_wpa_ctrl_status(&cli_status);
1630
1631 if (_res < 0) {
1632 ssid_len = 0;
1633 } else {
1634 ssid_len = cli_status.ssid_len;
1635 }
1636
1637 _ssid = cli_status.ssid;
1638 }
1639
1640 os_memcpy(status->ssid, _ssid, ssid_len);
1641 status->ssid_len = ssid_len;
1642 status->iface_mode = get_iface_mode(ssid->mode);
1643
1644 if (wpa_s->connection_set == 1) {
1645 status->link_mode = wpa_s->connection_he ? WIFI_6 :
1646 wpa_s->connection_vht ? WIFI_5 :
1647 wpa_s->connection_ht ? WIFI_4 :
1648 wpa_s->connection_g ? WIFI_3 :
1649 wpa_s->connection_a ? WIFI_2 :
1650 wpa_s->connection_b ? WIFI_1 :
1651 WIFI_0;
1652 } else {
1653 status->link_mode = WIFI_LINK_MODE_UNKNOWN;
1654 }
1655
1656 status->rssi = -WPA_INVALID_NOISE;
1657 if (status->iface_mode == WIFI_MODE_INFRA) {
1658 ret = z_wpa_ctrl_signal_poll(&signal_poll);
1659 if (!ret) {
1660 status->rssi = signal_poll.rssi;
1661 status->current_phy_tx_rate = signal_poll.current_txrate;
1662 } else {
1663 wpa_printf(MSG_WARNING, "%s: Failed to read signal poll info",
1664 __func__);
1665 }
1666 }
1667
1668 conn_info = os_zalloc(sizeof(struct wpa_conn_info));
1669 if (!conn_info) {
1670 wpa_printf(MSG_ERROR, "%s:Failed to allocate memory\n",
1671 __func__);
1672 ret = -ENOMEM;
1673 goto out;
1674 }
1675
1676 ret = wpa_drv_get_conn_info(wpa_s, conn_info);
1677 if (!ret) {
1678 status->beacon_interval = conn_info->beacon_interval;
1679 status->dtim_period = conn_info->dtim_period;
1680 status->twt_capable = conn_info->twt_capable;
1681 } else {
1682 wpa_printf(MSG_WARNING, "%s: Failed to get connection info\n",
1683 __func__);
1684
1685 status->beacon_interval = 0;
1686 status->dtim_period = 0;
1687 status->twt_capable = false;
1688 ret = 0;
1689 }
1690
1691 os_free(conn_info);
1692 } else {
1693 ret = 0;
1694 }
1695
1696 out:
1697 os_free(si);
1698 k_mutex_unlock(&wpa_supplicant_mutex);
1699 return ret;
1700 }
1701
1702 /* Below APIs are not natively supported by WPA supplicant, so,
1703 * these are just wrappers around driver offload APIs. But it is
1704 * transparent to the user.
1705 *
1706 * In the future these might be implemented natively by the WPA
1707 * supplicant.
1708 */
1709
1710 static const struct wifi_mgmt_ops *const get_wifi_mgmt_api(const struct device *dev)
1711 {
1712 struct net_wifi_mgmt_offload *api = (struct net_wifi_mgmt_offload *)dev->api;
1713
1714 return api ? api->wifi_mgmt_api : NULL;
1715 }
1716
1717 int supplicant_get_version(const struct device *dev, struct wifi_version *params)
1718 {
1719 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1720
1721 if (!wifi_mgmt_api || !wifi_mgmt_api->get_version) {
1722 wpa_printf(MSG_ERROR, "get_version not supported");
1723 return -ENOTSUP;
1724 }
1725
1726 return wifi_mgmt_api->get_version(dev, params);
1727 }
1728
1729 int supplicant_scan(const struct device *dev, struct wifi_scan_params *params,
1730 scan_result_cb_t cb)
1731 {
1732 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1733
1734 if (!wifi_mgmt_api || !wifi_mgmt_api->scan) {
1735 wpa_printf(MSG_ERROR, "Scan not supported");
1736 return -ENOTSUP;
1737 }
1738
1739 return wifi_mgmt_api->scan(dev, params, cb);
1740 }
1741
1742 #ifdef CONFIG_NET_STATISTICS_WIFI
1743 int supplicant_get_stats(const struct device *dev, struct net_stats_wifi *stats)
1744 {
1745 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1746
1747 if (!wifi_mgmt_api || !wifi_mgmt_api->get_stats) {
1748 wpa_printf(MSG_ERROR, "Get stats not supported");
1749 return -ENOTSUP;
1750 }
1751
1752 return wifi_mgmt_api->get_stats(dev, stats);
1753 }
1754
1755 int supplicant_reset_stats(const struct device *dev)
1756 {
1757 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1758
1759 if (!wifi_mgmt_api || !wifi_mgmt_api->reset_stats) {
1760 wpa_printf(MSG_WARNING, "Reset stats not supported");
1761 return -ENOTSUP;
1762 }
1763
1764 return wifi_mgmt_api->reset_stats(dev);
1765 }
1766 #endif /* CONFIG_NET_STATISTICS_WIFI */
1767
1768 int supplicant_pmksa_flush(const struct device *dev)
1769 {
1770 struct wpa_supplicant *wpa_s;
1771 int ret = 0;
1772
1773 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1774
1775 wpa_s = get_wpa_s_handle(dev);
1776 if (!wpa_s) {
1777 ret = -1;
1778 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
1779 goto out;
1780 }
1781
1782 if (!wpa_cli_cmd_v("pmksa_flush")) {
1783 ret = -1;
1784 wpa_printf(MSG_ERROR, "pmksa_flush failed");
1785 goto out;
1786 }
1787
1788 out:
1789 k_mutex_unlock(&wpa_supplicant_mutex);
1790 return ret;
1791 }
1792
1793 int supplicant_11k_cfg(const struct device *dev, struct wifi_11k_params *params)
1794 {
1795 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1796
1797 if (!wifi_mgmt_api || !wifi_mgmt_api->cfg_11k) {
1798 wpa_printf(MSG_ERROR, "cfg 11k not supported");
1799 return -ENOTSUP;
1800 }
1801
1802 return wifi_mgmt_api->cfg_11k(dev, params);
1803 }
1804
1805 int supplicant_11k_neighbor_request(const struct device *dev, struct wifi_11k_params *params)
1806 {
1807 int ssid_len = strlen(params->ssid);
1808
1809 if (params != NULL && ssid_len > 0) {
1810 if (ssid_len > WIFI_SSID_MAX_LEN) {
1811 wpa_printf(MSG_ERROR, "%s: ssid too long %u",
1812 __func__, ssid_len);
1813 return -1;
1814 }
1815
1816 if (!wpa_cli_cmd_v("neighbor_rep_request ssid %s",
1817 params->ssid)) {
1818 wpa_printf(MSG_ERROR,
1819 "%s: cli cmd <neighbor_rep_request ssid %s> fail",
1820 __func__, params->ssid);
1821 return -1;
1822 }
1823 } else {
1824 if (!wpa_cli_cmd_v("neighbor_rep_request")) {
1825 wpa_printf(MSG_ERROR,
1826 "%s: cli cmd <neighbor_rep_request> fail",
1827 __func__);
1828 return -1;
1829 }
1830 }
1831
1832 return 0;
1833 }
1834
1835 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_ROAMING
1836 #define SUPPLICANT_CANDIDATE_SCAN_CMD_BUF_SIZE 100
1837 int supplicant_candidate_scan(const struct device *dev, struct wifi_scan_params *params)
1838 {
1839 int i = 0;
1840 char cmd[SUPPLICANT_CANDIDATE_SCAN_CMD_BUF_SIZE] = {0};
1841 char *pos = cmd;
1842 char *end = pos + SUPPLICANT_CANDIDATE_SCAN_CMD_BUF_SIZE;
1843 int freq = 0;
1844
1845 strcpy(pos, "freq=");
1846 pos += 5;
1847 while (params->band_chan[i].channel) {
1848 if (i > 0) {
1849 pos += snprintf(pos, end - pos, ",");
1850 }
1851 freq = chan_to_freq(params->band_chan[i].channel);
1852 pos += snprintf(pos, end - pos, "%d", freq);
1853 i++;
1854 }
1855
1856 if (!wpa_cli_cmd_v("scan %s", cmd)) {
1857 wpa_printf(MSG_ERROR,
1858 "%s: cli cmd <scan %s> fail",
1859 __func__, cmd);
1860 return -1;
1861 }
1862
1863 return 0;
1864 }
1865
1866 int supplicant_11r_roaming(const struct device *dev)
1867 {
1868 struct wpa_supplicant *wpa_s;
1869 int ret = 0;
1870
1871 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1872
1873 wpa_s = get_wpa_s_handle(dev);
1874 if (!wpa_s) {
1875 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
1876 ret = -1;
1877 goto out;
1878 }
1879
1880 if (wpa_s->reassociate || (wpa_s->wpa_state >= WPA_AUTHENTICATING &&
1881 wpa_s->wpa_state < WPA_COMPLETED)) {
1882 wpa_printf(MSG_INFO, "Reassociation is in progress, skip");
1883 ret = 0;
1884 goto out;
1885 }
1886
1887 if (!wpa_cli_cmd_v("reassociate")) {
1888 wpa_printf(MSG_ERROR, "%s: cli cmd <reassociate> fail",
1889 __func__);
1890 ret = -1;
1891 goto out;
1892 }
1893
1894 out:
1895 k_mutex_unlock(&wpa_supplicant_mutex);
1896 return ret;
1897 }
1898 #endif
1899
1900 int supplicant_set_power_save(const struct device *dev, struct wifi_ps_params *params)
1901 {
1902 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1903
1904 if (!wifi_mgmt_api || !wifi_mgmt_api->set_power_save) {
1905 wpa_printf(MSG_ERROR, "Set power save not supported");
1906 return -ENOTSUP;
1907 }
1908
1909 return wifi_mgmt_api->set_power_save(dev, params);
1910 }
1911
1912 int supplicant_set_twt(const struct device *dev, struct wifi_twt_params *params)
1913 {
1914 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1915
1916 if (!wifi_mgmt_api || !wifi_mgmt_api->set_twt) {
1917 wpa_printf(MSG_ERROR, "Set TWT not supported");
1918 return -ENOTSUP;
1919 }
1920
1921 return wifi_mgmt_api->set_twt(dev, params);
1922 }
1923
1924 int supplicant_set_btwt(const struct device *dev, struct wifi_twt_params *params)
1925 {
1926 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1927
1928 if (!wifi_mgmt_api || !wifi_mgmt_api->set_btwt) {
1929 wpa_printf(MSG_ERROR, "Set Broadcast TWT not supported");
1930 return -ENOTSUP;
1931 }
1932
1933 return wifi_mgmt_api->set_btwt(dev, params);
1934 }
1935
1936 int supplicant_get_power_save_config(const struct device *dev,
1937 struct wifi_ps_config *config)
1938 {
1939 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1940
1941 if (!wifi_mgmt_api || !wifi_mgmt_api->get_power_save_config) {
1942 wpa_printf(MSG_ERROR, "Get power save config not supported");
1943 return -ENOTSUP;
1944 }
1945
1946 return wifi_mgmt_api->get_power_save_config(dev, config);
1947 }
1948
1949 int supplicant_reg_domain(const struct device *dev,
1950 struct wifi_reg_domain *reg_domain)
1951 {
1952 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1953 struct wpa_supplicant *wpa_s;
1954 int ret = -1;
1955
1956 if (!wifi_mgmt_api || !wifi_mgmt_api->reg_domain) {
1957 wpa_printf(MSG_ERROR, "Regulatory domain not supported");
1958 return -ENOTSUP;
1959 }
1960
1961 if (reg_domain->oper == WIFI_MGMT_GET) {
1962 return wifi_mgmt_api->reg_domain(dev, reg_domain);
1963 }
1964
1965 if (reg_domain->oper == WIFI_MGMT_SET) {
1966 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1967
1968 wpa_s = get_wpa_s_handle(dev);
1969 if (!wpa_s) {
1970 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
1971 goto out;
1972 }
1973
1974 if (!wpa_cli_cmd_v("set country %s", reg_domain->country_code)) {
1975 goto out;
1976 }
1977
1978 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
1979 if (!hostapd_cli_cmd_v("set country_code %s", reg_domain->country_code)) {
1980 goto out;
1981 }
1982 #endif
1983
1984 ret = 0;
1985
1986 out:
1987 k_mutex_unlock(&wpa_supplicant_mutex);
1988 }
1989
1990 return ret;
1991 }
1992
1993 int supplicant_mode(const struct device *dev, struct wifi_mode_info *mode)
1994 {
1995 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1996
1997 if (!wifi_mgmt_api || !wifi_mgmt_api->mode) {
1998 wpa_printf(MSG_ERROR, "Setting mode not supported");
1999 return -ENOTSUP;
2000 }
2001
2002 return wifi_mgmt_api->mode(dev, mode);
2003 }
2004
2005 int supplicant_filter(const struct device *dev, struct wifi_filter_info *filter)
2006 {
2007 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
2008
2009 if (!wifi_mgmt_api || !wifi_mgmt_api->filter) {
2010 wpa_printf(MSG_ERROR, "Setting filter not supported");
2011 return -ENOTSUP;
2012 }
2013
2014 return wifi_mgmt_api->filter(dev, filter);
2015 }
2016
2017 int supplicant_channel(const struct device *dev, struct wifi_channel_info *channel)
2018 {
2019 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
2020
2021 if (!wifi_mgmt_api || !wifi_mgmt_api->channel) {
2022 wpa_printf(MSG_ERROR, "Setting channel not supported");
2023 return -ENOTSUP;
2024 }
2025
2026 return wifi_mgmt_api->channel(dev, channel);
2027 }
2028
2029 int supplicant_set_rts_threshold(const struct device *dev, unsigned int rts_threshold)
2030 {
2031 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
2032
2033 if (!wifi_mgmt_api || !wifi_mgmt_api->set_rts_threshold) {
2034 wpa_printf(MSG_ERROR, "Set RTS not supported");
2035 return -ENOTSUP;
2036 }
2037
2038 return wifi_mgmt_api->set_rts_threshold(dev, rts_threshold);
2039 }
2040
2041 int supplicant_get_rts_threshold(const struct device *dev, unsigned int *rts_threshold)
2042 {
2043 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
2044
2045 if (!wifi_mgmt_api || !wifi_mgmt_api->get_rts_threshold) {
2046 wpa_printf(MSG_ERROR, "Get RTS not supported");
2047 return -ENOTSUP;
2048 }
2049
2050 return wifi_mgmt_api->get_rts_threshold(dev, rts_threshold);
2051 }
2052
2053 int supplicant_bss_ext_capab(const struct device *dev, int capab)
2054 {
2055 struct wpa_supplicant *wpa_s;
2056 int is_support = 0;
2057
2058 wpa_s = get_wpa_s_handle(dev);
2059 if (!wpa_s) {
2060 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2061 return 0;
2062 }
2063
2064 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2065 is_support = wpa_bss_ext_capab(wpa_s->current_bss, capab);
2066 k_mutex_unlock(&wpa_supplicant_mutex);
2067
2068 return is_support;
2069 }
2070
2071 int supplicant_legacy_roam(const struct device *dev)
2072 {
2073 int ret = -1;
2074
2075 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2076 if (!wpa_cli_cmd_v("scan")) {
2077 goto out;
2078 }
2079
2080 ret = 0;
2081
2082 out:
2083 k_mutex_unlock(&wpa_supplicant_mutex);
2084
2085 return ret;
2086 }
2087
2088 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_WNM
2089 int supplicant_btm_query(const struct device *dev, uint8_t reason)
2090 {
2091 struct wpa_supplicant *wpa_s;
2092 int ret = -1;
2093
2094 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2095
2096 wpa_s = get_wpa_s_handle(dev);
2097 if (!wpa_s) {
2098 ret = -1;
2099 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2100 goto out;
2101 }
2102
2103 if (!wpa_cli_cmd_v("wnm_bss_query %d", reason)) {
2104 goto out;
2105 }
2106
2107 ret = 0;
2108
2109 out:
2110 k_mutex_unlock(&wpa_supplicant_mutex);
2111
2112 return ret;
2113 }
2114 #endif
2115
2116 int supplicant_get_wifi_conn_params(const struct device *dev,
2117 struct wifi_connect_req_params *params)
2118 {
2119 struct wpa_supplicant *wpa_s;
2120 int ret = 0;
2121
2122 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2123
2124 wpa_s = get_wpa_s_handle(dev);
2125 if (!wpa_s) {
2126 ret = -1;
2127 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
2128 goto out;
2129 }
2130
2131 memcpy(params, &last_wifi_conn_params, sizeof(struct wifi_connect_req_params));
2132 out:
2133 k_mutex_unlock(&wpa_supplicant_mutex);
2134 return ret;
2135 }
2136
2137 static int supplicant_wps_pbc(const struct device *dev)
2138 {
2139 struct wpa_supplicant *wpa_s;
2140 int ret = -1;
2141
2142 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2143
2144 wpa_s = get_wpa_s_handle(dev);
2145 if (!wpa_s) {
2146 ret = -1;
2147 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2148 goto out;
2149 }
2150
2151 if (!wpa_cli_cmd_v("wps_pbc")) {
2152 goto out;
2153 }
2154
2155 wpas_api_ctrl.dev = dev;
2156 wpas_api_ctrl.requested_op = WPS_PBC;
2157
2158 ret = 0;
2159
2160 out:
2161 k_mutex_unlock(&wpa_supplicant_mutex);
2162
2163 return ret;
2164 }
2165
2166 static int supplicant_wps_pin(const struct device *dev, struct wifi_wps_config_params *params)
2167 {
2168 struct wpa_supplicant *wpa_s;
2169 char *get_pin_cmd = "WPS_PIN get";
2170 int ret = -1;
2171
2172 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2173
2174 wpa_s = get_wpa_s_handle(dev);
2175 if (!wpa_s) {
2176 ret = -1;
2177 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2178 goto out;
2179 }
2180
2181 if (params->oper == WIFI_WPS_PIN_GET) {
2182 if (zephyr_wpa_cli_cmd_resp(get_pin_cmd, params->pin)) {
2183 goto out;
2184 }
2185 } else if (params->oper == WIFI_WPS_PIN_SET) {
2186 if (!wpa_cli_cmd_v("wps_check_pin %s", params->pin)) {
2187 goto out;
2188 }
2189
2190 if (!wpa_cli_cmd_v("wps_pin any %s", params->pin)) {
2191 goto out;
2192 }
2193
2194 wpas_api_ctrl.dev = dev;
2195 wpas_api_ctrl.requested_op = WPS_PIN;
2196 } else {
2197 wpa_printf(MSG_ERROR, "Error wps pin operation : %d", params->oper);
2198 goto out;
2199 }
2200
2201 ret = 0;
2202
2203 out:
2204 k_mutex_unlock(&wpa_supplicant_mutex);
2205
2206 return ret;
2207 }
2208
2209 int supplicant_wps_config(const struct device *dev, struct wifi_wps_config_params *params)
2210 {
2211 int ret = 0;
2212
2213 if (params->oper == WIFI_WPS_PBC) {
2214 ret = supplicant_wps_pbc(dev);
2215 } else if (params->oper == WIFI_WPS_PIN_GET || params->oper == WIFI_WPS_PIN_SET) {
2216 ret = supplicant_wps_pin(dev, params);
2217 }
2218
2219 return ret;
2220 }
2221
2222 #ifdef CONFIG_AP
2223 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
2224 int hapd_state(const struct device *dev, int *state)
2225 {
2226 struct hostapd_iface *iface;
2227 int ret = 0;
2228
2229 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2230
2231 iface = get_hostapd_handle(dev);
2232 if (!iface) {
2233 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
2234 ret = -ENOENT;
2235 goto out;
2236 }
2237
2238 *state = iface->state;
2239
2240 out:
2241 k_mutex_unlock(&wpa_supplicant_mutex);
2242 return ret;
2243 }
2244
2245 static int hapd_config_chan_center_seg0(struct wifi_connect_req_params *params)
2246 {
2247 int ret = 0;
2248 uint8_t center_freq_seg0_idx = 0;
2249 uint8_t oper_chwidth = CHANWIDTH_USE_HT;
2250 const uint8_t *center_freq = NULL;
2251 static const uint8_t center_freq_40MHz[] = {38, 46, 54, 62, 102, 110,
2252 118, 126, 134, 142, 151, 159};
2253 static const uint8_t center_freq_80MHz[] = {42, 58, 106, 122, 138, 155};
2254 uint8_t index, index_max, chan_idx, ch_offset = 0;
2255
2256 /* Unless ACS is being used, both "channel" and "vht_oper_centr_freq_seg0_idx"
2257 * parameters must be set.
2258 */
2259 switch (params->bandwidth) {
2260 case WIFI_FREQ_BANDWIDTH_20MHZ:
2261 oper_chwidth = CHANWIDTH_USE_HT;
2262 center_freq_seg0_idx = params->channel;
2263 break;
2264 case WIFI_FREQ_BANDWIDTH_40MHZ:
2265 oper_chwidth = CHANWIDTH_USE_HT;
2266 center_freq = center_freq_40MHz;
2267 index_max = ARRAY_SIZE(center_freq_40MHz);
2268 ch_offset = 2;
2269 break;
2270 case WIFI_FREQ_BANDWIDTH_80MHZ:
2271 oper_chwidth = CHANWIDTH_80MHZ;
2272 center_freq = center_freq_80MHz;
2273 index_max = ARRAY_SIZE(center_freq_80MHz);
2274 ch_offset = 6;
2275 break;
2276 default:
2277 return -EINVAL;
2278 }
2279
2280 if (params->bandwidth != WIFI_FREQ_BANDWIDTH_20MHZ) {
2281 chan_idx = params->channel;
2282 for (index = 0; index < index_max; index++) {
2283 if ((chan_idx >= (center_freq[index] - ch_offset)) &&
2284 (chan_idx <= (center_freq[index] + ch_offset))) {
2285 center_freq_seg0_idx = center_freq[index];
2286 break;
2287 }
2288 }
2289 }
2290
2291 if (!hostapd_cli_cmd_v("set vht_oper_chwidth %d", oper_chwidth)) {
2292 goto out;
2293 }
2294 if (!hostapd_cli_cmd_v("set vht_oper_centr_freq_seg0_idx %d", center_freq_seg0_idx)) {
2295 goto out;
2296 }
2297 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_11AX
2298 if (!hostapd_cli_cmd_v("set he_oper_chwidth %d", oper_chwidth)) {
2299 goto out;
2300 }
2301 if (!hostapd_cli_cmd_v("set he_oper_centr_freq_seg0_idx %d", center_freq_seg0_idx)) {
2302 goto out;
2303 }
2304 #endif
2305
2306 return ret;
2307 out:
2308 return -EINVAL;
2309 }
2310
2311 int hapd_config_network(struct hostapd_iface *iface,
2312 struct wifi_connect_req_params *params)
2313 {
2314 int ret = 0;
2315
2316 if (!hostapd_cli_cmd_v("set ssid %s", params->ssid)) {
2317 goto out;
2318 }
2319
2320 if (params->channel == 0) {
2321 if (params->band == 0) {
2322 if (!hostapd_cli_cmd_v("set hw_mode g")) {
2323 goto out;
2324 }
2325 } else if (params->band == 1) {
2326 if (!hostapd_cli_cmd_v("set hw_mode a")) {
2327 goto out;
2328 }
2329 } else {
2330 wpa_printf(MSG_ERROR, "Invalid band %d", params->band);
2331 goto out;
2332 }
2333 } else if (params->channel > 14) {
2334 if (!hostapd_cli_cmd_v("set hw_mode a")) {
2335 goto out;
2336 }
2337 } else {
2338 if (!hostapd_cli_cmd_v("set hw_mode g")) {
2339 goto out;
2340 }
2341 }
2342
2343 if (!hostapd_cli_cmd_v("set channel %d", params->channel)) {
2344 goto out;
2345 }
2346
2347 ret = hapd_config_chan_center_seg0(params);
2348 if (ret) {
2349 goto out;
2350 }
2351
2352 if (params->security != WIFI_SECURITY_TYPE_NONE) {
2353 if (params->security == WIFI_SECURITY_TYPE_WPA_PSK) {
2354 if (!hostapd_cli_cmd_v("set wpa 1")) {
2355 goto out;
2356 }
2357 if (!hostapd_cli_cmd_v("set wpa_key_mgmt WPA-PSK")) {
2358 goto out;
2359 }
2360 if (!hostapd_cli_cmd_v("set wpa_passphrase %s", params->psk)) {
2361 goto out;
2362 }
2363 if (!hostapd_cli_cmd_v("set wpa_pairwise CCMP")) {
2364 goto out;
2365 }
2366 } else if (params->security == WIFI_SECURITY_TYPE_PSK) {
2367 if (!hostapd_cli_cmd_v("set wpa 2")) {
2368 goto out;
2369 }
2370 if (!hostapd_cli_cmd_v("set wpa_key_mgmt WPA-PSK")) {
2371 goto out;
2372 }
2373 if (!hostapd_cli_cmd_v("set wpa_passphrase %s", params->psk)) {
2374 goto out;
2375 }
2376 if (!hostapd_cli_cmd_v("set rsn_pairwise CCMP")) {
2377 goto out;
2378 }
2379 } else if (params->security == WIFI_SECURITY_TYPE_PSK_SHA256) {
2380 if (!hostapd_cli_cmd_v("set wpa 2")) {
2381 goto out;
2382 }
2383 if (!hostapd_cli_cmd_v("set wpa_key_mgmt WPA-PSK-SHA256")) {
2384 goto out;
2385 }
2386 if (!hostapd_cli_cmd_v("set wpa_passphrase %s", params->psk)) {
2387 goto out;
2388 }
2389 if (!hostapd_cli_cmd_v("set rsn_pairwise CCMP")) {
2390 goto out;
2391 }
2392 } else if (params->security == WIFI_SECURITY_TYPE_SAE_HNP ||
2393 params->security == WIFI_SECURITY_TYPE_SAE_H2E ||
2394 params->security == WIFI_SECURITY_TYPE_SAE_AUTO) {
2395 if (!hostapd_cli_cmd_v("set wpa 2")) {
2396 goto out;
2397 }
2398 if (!hostapd_cli_cmd_v("set wpa_key_mgmt SAE")) {
2399 goto out;
2400 }
2401 if (!hostapd_cli_cmd_v("set sae_password %s",
2402 params->sae_password ? params->sae_password :
2403 params->psk)) {
2404 goto out;
2405 }
2406 if (!hostapd_cli_cmd_v("set rsn_pairwise CCMP")) {
2407 goto out;
2408 }
2409 if (params->security == WIFI_SECURITY_TYPE_SAE_H2E ||
2410 params->security == WIFI_SECURITY_TYPE_SAE_AUTO) {
2411 if (!hostapd_cli_cmd_v("set sae_pwe %d",
2412 (params->security == WIFI_SECURITY_TYPE_SAE_H2E)
2413 ? 1
2414 : 2)) {
2415 goto out;
2416 }
2417 }
2418 } else if (params->security == WIFI_SECURITY_TYPE_WPA_AUTO_PERSONAL) {
2419 if (!hostapd_cli_cmd_v("set wpa 2")) {
2420 goto out;
2421 }
2422
2423 if (!hostapd_cli_cmd_v("set wpa_key_mgmt WPA-PSK SAE")) {
2424 goto out;
2425 }
2426
2427 if (!hostapd_cli_cmd_v("set wpa_passphrase %s", params->psk)) {
2428 goto out;
2429 }
2430
2431 if (!hostapd_cli_cmd_v("set sae_password %s",
2432 params->sae_password ? params->sae_password
2433 : params->psk)) {
2434 goto out;
2435 }
2436
2437 if (!hostapd_cli_cmd_v("set rsn_pairwise CCMP")) {
2438 goto out;
2439 }
2440
2441 if (!hostapd_cli_cmd_v("set sae_pwe 2")) {
2442 goto out;
2443 }
2444 } else if (params->security == WIFI_SECURITY_TYPE_DPP) {
2445 if (!hostapd_cli_cmd_v("set wpa 2")) {
2446 goto out;
2447 }
2448 if (!hostapd_cli_cmd_v("set wpa_key_mgmt WPA-PSK DPP")) {
2449 goto out;
2450 }
2451 if (!hostapd_cli_cmd_v("set wpa_passphrase %s", params->psk)) {
2452 goto out;
2453 }
2454 if (!hostapd_cli_cmd_v("set wpa_pairwise CCMP")) {
2455 goto out;
2456 }
2457 if (!hostapd_cli_cmd_v("set rsn_pairwise CCMP")) {
2458 goto out;
2459 }
2460 if (!hostapd_cli_cmd_v("set dpp_configurator_connectivity 1")) {
2461 goto out;
2462 }
2463 #ifdef CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE
2464 } else if (is_eap_valid_security(params->security)) {
2465 if (hapd_process_enterprise_config(iface, params)) {
2466 goto out;
2467 }
2468 #endif
2469 } else {
2470 wpa_printf(MSG_ERROR, "Security type %d is not supported",
2471 params->security);
2472 goto out;
2473 }
2474 } else {
2475 if (!hostapd_cli_cmd_v("set wpa 0")) {
2476 goto out;
2477 }
2478 iface->bss[0]->conf->wpa_key_mgmt = WPA_KEY_MGMT_NONE;
2479 }
2480
2481 if (!hostapd_cli_cmd_v("set ieee80211w %d", params->mfp)) {
2482 goto out;
2483 }
2484
2485 if (!hostapd_cli_cmd_v("set ignore_broadcast_ssid %d", params->ignore_broadcast_ssid)) {
2486 goto out;
2487 }
2488
2489 return ret;
2490 out:
2491 return -1;
2492 }
2493
2494 static int set_ap_config_params(const struct device *dev, struct wifi_ap_config_params *params)
2495 {
2496 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
2497
2498 if (wifi_mgmt_api == NULL || wifi_mgmt_api->ap_config_params == NULL) {
2499 return -ENOTSUP;
2500 }
2501
2502 return wifi_mgmt_api->ap_config_params(dev, params);
2503 }
2504
2505 int supplicant_ap_config_params(const struct device *dev, struct wifi_ap_config_params *params)
2506 {
2507 struct hostapd_iface *iface;
2508 int ret = 0;
2509
2510 ret = set_ap_config_params(dev, params);
2511 if (ret && (ret != -ENOTSUP)) {
2512 wpa_printf(MSG_ERROR, "Failed to set ap config params");
2513 return -EINVAL;
2514 }
2515
2516 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2517
2518 iface = get_hostapd_handle(dev);
2519 if (iface == NULL) {
2520 ret = -ENOENT;
2521 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2522 goto out;
2523 }
2524
2525 if (iface->state > HAPD_IFACE_DISABLED) {
2526 ret = -EBUSY;
2527 wpa_printf(MSG_ERROR, "Interface %s is not in disable state", dev->name);
2528 goto out;
2529 }
2530
2531 if (params->type & WIFI_AP_CONFIG_PARAM_MAX_NUM_STA) {
2532 if (!hostapd_cli_cmd_v("set max_num_sta %d", params->max_num_sta)) {
2533 ret = -EINVAL;
2534 wpa_printf(MSG_ERROR, "Failed to set maximum number of stations");
2535 goto out;
2536 }
2537 wpa_printf(MSG_INFO, "Set maximum number of stations: %d", params->max_num_sta);
2538 }
2539
2540 if (params->type & WIFI_AP_CONFIG_PARAM_HT_CAPAB) {
2541 if (!hostapd_cli_cmd_v("set ht_capab %s", params->ht_capab)) {
2542 ret = -EINVAL;
2543 wpa_printf(MSG_ERROR, "Failed to set HT capabilities");
2544 goto out;
2545 }
2546 wpa_printf(MSG_INFO, "Set HT capabilities: %s", params->ht_capab);
2547 }
2548
2549 if (params->type & WIFI_AP_CONFIG_PARAM_VHT_CAPAB) {
2550 if (!hostapd_cli_cmd_v("set vht_capab %s", params->vht_capab)) {
2551 ret = -EINVAL;
2552 wpa_printf(MSG_ERROR, "Failed to set VHT capabilities");
2553 goto out;
2554 }
2555 wpa_printf(MSG_INFO, "Set VHT capabilities: %s", params->vht_capab);
2556 }
2557
2558 out:
2559 k_mutex_unlock(&wpa_supplicant_mutex);
2560
2561 return ret;
2562 }
2563
2564 int supplicant_ap_status(const struct device *dev, struct wifi_iface_status *status)
2565 {
2566 int ret = 0;
2567 struct hostapd_iface *iface;
2568 struct hostapd_config *conf;
2569 struct hostapd_data *hapd;
2570 struct hostapd_bss_config *bss;
2571 struct hostapd_ssid *ssid;
2572 struct hostapd_hw_modes *hw_mode;
2573 int proto; /* Wi-Fi secure protocol */
2574 int key_mgmt; /* Wi-Fi key management */
2575 int sae_pwe;
2576
2577 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2578
2579 iface = get_hostapd_handle(dev);
2580 if (!iface) {
2581 ret = -1;
2582 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2583 goto out;
2584 }
2585
2586 conf = iface->conf;
2587 if (!conf) {
2588 ret = -1;
2589 wpa_printf(MSG_ERROR, "Conf %s not found", dev->name);
2590 goto out;
2591 }
2592
2593 bss = conf->bss[0];
2594 if (!bss) {
2595 ret = -1;
2596 wpa_printf(MSG_ERROR, "Bss_conf %s not found", dev->name);
2597 goto out;
2598 }
2599
2600 hapd = iface->bss[0];
2601 if (!hapd) {
2602 ret = -1;
2603 wpa_printf(MSG_ERROR, "Bss %s not found", dev->name);
2604 goto out;
2605 }
2606
2607 status->state = iface->state;
2608 ssid = &bss->ssid;
2609
2610 os_memcpy(status->bssid, hapd->own_addr, WIFI_MAC_ADDR_LEN);
2611 status->iface_mode = WIFI_MODE_AP;
2612 status->band = wpas_band_to_zephyr(wpas_freq_to_band(iface->freq));
2613 key_mgmt = bss->wpa_key_mgmt;
2614 proto = bss->wpa;
2615 sae_pwe = bss->sae_pwe;
2616 status->wpa3_ent_type = wpas_key_mgmt_to_zephyr_wpa3_ent(key_mgmt);
2617 status->security = wpas_key_mgmt_to_zephyr(1, hapd->conf, key_mgmt, proto, sae_pwe);
2618 status->mfp = get_mfp(bss->ieee80211w);
2619 status->channel = conf->channel;
2620 os_memcpy(status->ssid, ssid->ssid, ssid->ssid_len);
2621
2622 status->dtim_period = bss->dtim_period;
2623 status->beacon_interval = conf->beacon_int;
2624
2625 hw_mode = iface->current_mode;
2626
2627 status->link_mode = conf->ieee80211ax ? WIFI_6
2628 : conf->ieee80211ac ? WIFI_5
2629 : conf->ieee80211n ? WIFI_4
2630 : hw_mode->mode == HOSTAPD_MODE_IEEE80211G ? WIFI_3
2631 : hw_mode->mode == HOSTAPD_MODE_IEEE80211A ? WIFI_2
2632 : hw_mode->mode == HOSTAPD_MODE_IEEE80211B ? WIFI_1
2633 : WIFI_0;
2634 status->twt_capable = (hw_mode->he_capab[IEEE80211_MODE_AP].mac_cap[0] & 0x04);
2635
2636 out:
2637 k_mutex_unlock(&wpa_supplicant_mutex);
2638 return ret;
2639 }
2640 #endif /* CONFIG_WIFI_NM_HOSTAPD_AP */
2641
2642 #ifdef CONFIG_WIFI_NM_HOSTAPD_WPS
2643 int supplicant_ap_wps_pbc(const struct device *dev)
2644 {
2645 struct hostapd_iface *iface;
2646 int ret = -1;
2647
2648 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2649
2650 iface = get_hostapd_handle(dev);
2651 if (!iface) {
2652 ret = -1;
2653 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2654 goto out;
2655 }
2656
2657 if (iface->state != HAPD_IFACE_ENABLED) {
2658 ret = -EBUSY;
2659 wpa_printf(MSG_ERROR, "Interface %s is not in enable state", dev->name);
2660 goto out;
2661 }
2662
2663 if (!hostapd_cli_cmd_v("wps_pbc")) {
2664 goto out;
2665 }
2666
2667 wpas_api_ctrl.dev = dev;
2668 wpas_api_ctrl.requested_op = WPS_PBC;
2669
2670 ret = 0;
2671
2672 out:
2673 k_mutex_unlock(&wpa_supplicant_mutex);
2674
2675 return ret;
2676 }
2677
2678 int supplicant_ap_wps_pin(const struct device *dev, struct wifi_wps_config_params *params)
2679 {
2680 #define WPS_PIN_EXPIRE_TIME 120
2681 struct hostapd_iface *iface;
2682 char *get_pin_cmd = "WPS_AP_PIN random";
2683 int ret = 0;
2684
2685 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2686
2687 iface = get_hostapd_handle(dev);
2688 if (!iface) {
2689 ret = -1;
2690 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2691 goto out;
2692 }
2693
2694 if (iface->state != HAPD_IFACE_ENABLED) {
2695 ret = -EBUSY;
2696 wpa_printf(MSG_ERROR, "Interface %s is not in enable state", dev->name);
2697 goto out;
2698 }
2699
2700 if (params->oper == WIFI_WPS_PIN_GET) {
2701 if (zephyr_hostapd_cli_cmd_resp(get_pin_cmd, params->pin)) {
2702 goto out;
2703 }
2704 } else if (params->oper == WIFI_WPS_PIN_SET) {
2705 if (!hostapd_cli_cmd_v("wps_check_pin %s", params->pin)) {
2706 goto out;
2707 }
2708
2709 if (!hostapd_cli_cmd_v("wps_pin any %s %d", params->pin, WPS_PIN_EXPIRE_TIME)) {
2710 goto out;
2711 }
2712
2713 wpas_api_ctrl.dev = dev;
2714 wpas_api_ctrl.requested_op = WPS_PIN;
2715 } else {
2716 wpa_printf(MSG_ERROR, "Error wps pin operation : %d", params->oper);
2717 goto out;
2718 }
2719
2720 ret = 0;
2721
2722 out:
2723 k_mutex_unlock(&wpa_supplicant_mutex);
2724
2725 return ret;
2726 }
2727
2728
2729 int supplicant_ap_wps_config(const struct device *dev, struct wifi_wps_config_params *params)
2730 {
2731 int ret = 0;
2732
2733 if (params->oper == WIFI_WPS_PBC) {
2734 ret = supplicant_ap_wps_pbc(dev);
2735 } else if (params->oper == WIFI_WPS_PIN_GET || params->oper == WIFI_WPS_PIN_SET) {
2736 ret = supplicant_ap_wps_pin(dev, params);
2737 }
2738
2739 return ret;
2740 }
2741 #endif
2742
2743 static int set_ap_bandwidth(const struct device *dev, enum wifi_frequency_bandwidths bandwidth)
2744 {
2745 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
2746 struct wifi_ap_config_params params = {0};
2747
2748 if (wifi_mgmt_api == NULL || wifi_mgmt_api->ap_config_params == NULL) {
2749 return -ENOTSUP;
2750 }
2751
2752 params.bandwidth = bandwidth;
2753 params.type = WIFI_AP_CONFIG_PARAM_BANDWIDTH;
2754 return wifi_mgmt_api->ap_config_params(dev, ¶ms);
2755 }
2756
2757 int supplicant_ap_enable(const struct device *dev,
2758 struct wifi_connect_req_params *params)
2759 {
2760 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
2761 struct hostapd_iface *iface;
2762 struct hostapd_data *hapd;
2763 struct wpa_driver_capa capa;
2764 #else
2765 struct wpa_supplicant *wpa_s;
2766 #endif
2767 int ret;
2768
2769 if (!net_if_is_admin_up(net_if_lookup_by_dev(dev))) {
2770 wpa_printf(MSG_ERROR,
2771 "Interface %s is down, dropping connect",
2772 dev->name);
2773 return -1;
2774 }
2775
2776 ret = set_ap_bandwidth(dev, params->bandwidth);
2777 if (ret && (ret != -ENOTSUP)) {
2778 wpa_printf(MSG_ERROR, "Failed to set ap bandwidth");
2779 return -EINVAL;
2780 }
2781
2782 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2783
2784 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
2785 iface = get_hostapd_handle(dev);
2786 if (!iface) {
2787 ret = -1;
2788 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2789 goto out;
2790 }
2791
2792 iface->owner = iface;
2793
2794 if (iface->state == HAPD_IFACE_ENABLED) {
2795 ret = -EBUSY;
2796 wpa_printf(MSG_ERROR, "Interface %s is not in disable state", dev->name);
2797 goto out;
2798 }
2799
2800 ret = hapd_config_network(iface, params);
2801 if (ret) {
2802 wpa_printf(MSG_ERROR, "Failed to configure network for AP: %d", ret);
2803 goto out;
2804 }
2805
2806 hapd = iface->bss[0];
2807 if (!iface->extended_capa || !iface->extended_capa_mask) {
2808 if (hapd->driver->get_capa && hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) {
2809 iface->extended_capa = capa.extended_capa;
2810 iface->extended_capa_mask = capa.extended_capa_mask;
2811 iface->extended_capa_len = capa.extended_capa_len;
2812 iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
2813
2814 /*
2815 * Override extended capa with per-interface type (AP), if
2816 * available from the driver.
2817 */
2818 hostapd_get_ext_capa(iface);
2819 } else {
2820 ret = -1;
2821 wpa_printf(MSG_ERROR, "Failed to get capability for AP: %d", ret);
2822 goto out;
2823 }
2824 }
2825
2826 if (!hostapd_cli_cmd_v("enable")) {
2827 goto out;
2828 }
2829
2830 #else
2831 wpa_s = get_wpa_s_handle(dev);
2832 if (!wpa_s) {
2833 ret = -1;
2834 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2835 goto out;
2836 }
2837
2838 if (wpa_s->wpa_state != WPA_DISCONNECTED) {
2839 ret = -EBUSY;
2840 wpa_printf(MSG_ERROR, "Interface %s is not in disconnected state", dev->name);
2841 goto out;
2842 }
2843
2844 /* No need to check for existing network to join for SoftAP */
2845 wpa_s->conf->ap_scan = 2;
2846 /* Set BSS parameter max_num_sta to default configured value */
2847 wpa_s->conf->max_num_sta = CONFIG_WIFI_MGMT_AP_MAX_NUM_STA;
2848
2849 ret = wpas_add_and_config_network(wpa_s, params, true);
2850 if (ret) {
2851 wpa_printf(MSG_ERROR, "Failed to add and configure network for AP mode: %d", ret);
2852 goto out;
2853 }
2854 #endif
2855
2856 out:
2857 k_mutex_unlock(&wpa_supplicant_mutex);
2858
2859 return ret;
2860 }
2861
2862 int supplicant_ap_disable(const struct device *dev)
2863 {
2864 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
2865 struct hostapd_iface *iface;
2866 int ret = 0;
2867 #else
2868 struct wpa_supplicant *wpa_s;
2869 int ret = -1;
2870 #endif
2871
2872 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2873
2874 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
2875 iface = get_hostapd_handle(dev);
2876 if (!iface) {
2877 ret = -ENOENT;
2878 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2879 goto out;
2880 }
2881
2882 if (iface->state != HAPD_IFACE_ENABLED) {
2883 ret = -EBUSY;
2884 wpa_printf(MSG_ERROR, "Interface %s is not in enable state", dev->name);
2885 goto out;
2886 }
2887
2888 if (!hostapd_cli_cmd_v("disable")) {
2889 goto out;
2890 }
2891
2892 iface->freq = 0;
2893 #else
2894 wpa_s = get_wpa_s_handle(dev);
2895 if (!wpa_s) {
2896 ret = -1;
2897 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2898 goto out;
2899 }
2900
2901 ret = wpas_disconnect_network(dev, WPAS_MODE_AP);
2902 if (ret) {
2903 wpa_printf(MSG_ERROR, "Failed to disconnect from network");
2904 goto out;
2905 }
2906
2907 /* Restore ap_scan to default value */
2908 wpa_s->conf->ap_scan = 1;
2909 #endif
2910
2911 out:
2912 k_mutex_unlock(&wpa_supplicant_mutex);
2913 return ret;
2914 }
2915
2916 int supplicant_ap_sta_disconnect(const struct device *dev,
2917 const uint8_t *mac_addr)
2918 {
2919 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
2920 struct hostapd_iface *iface;
2921 int ret = 0;
2922 #else
2923 struct wpa_supplicant *wpa_s;
2924 int ret = -1;
2925 #endif
2926
2927 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2928
2929 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
2930 iface = get_hostapd_handle(dev);
2931 if (!iface) {
2932 ret = -1;
2933 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2934 goto out;
2935 }
2936
2937 if (iface->state != HAPD_IFACE_ENABLED) {
2938 ret = -EBUSY;
2939 wpa_printf(MSG_ERROR, "Interface %s is not in enable state", dev->name);
2940 goto out;
2941 }
2942
2943 if (!mac_addr) {
2944 ret = -EINVAL;
2945 wpa_printf(MSG_ERROR, "Invalid MAC address");
2946 goto out;
2947 }
2948
2949 if (!hostapd_cli_cmd_v("deauthenticate %02x:%02x:%02x:%02x:%02x:%02x",
2950 mac_addr[0], mac_addr[1], mac_addr[2],
2951 mac_addr[3], mac_addr[4], mac_addr[5])) {
2952 goto out;
2953 }
2954
2955 #else
2956 wpa_s = get_wpa_s_handle(dev);
2957 if (!wpa_s) {
2958 ret = -1;
2959 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2960 goto out;
2961 }
2962
2963 if (!mac_addr) {
2964 ret = -EINVAL;
2965 wpa_printf(MSG_ERROR, "Invalid MAC address");
2966 goto out;
2967 }
2968
2969 if (!wpa_cli_cmd_v("disassociate %02x:%02x:%02x:%02x:%02x:%02x",
2970 mac_addr[0], mac_addr[1], mac_addr[2],
2971 mac_addr[3], mac_addr[4], mac_addr[5])) {
2972 goto out;
2973 }
2974
2975 ret = 0;
2976 #endif
2977
2978 out:
2979 k_mutex_unlock(&wpa_supplicant_mutex);
2980
2981 return ret;
2982 }
2983 #endif /* CONFIG_AP */
2984
2985 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP
2986 static const char *dpp_params_to_args_curve(int curve)
2987 {
2988 switch (curve) {
2989 case WIFI_DPP_CURVES_P_256:
2990 return "P-256";
2991 case WIFI_DPP_CURVES_P_384:
2992 return "P-384";
2993 case WIFI_DPP_CURVES_P_512:
2994 return "P-521";
2995 case WIFI_DPP_CURVES_BP_256:
2996 return "BP-256";
2997 case WIFI_DPP_CURVES_BP_384:
2998 return "BP-384";
2999 case WIFI_DPP_CURVES_BP_512:
3000 return "BP-512";
3001 default:
3002 return "P-256";
3003 }
3004 }
3005
3006 static const char *dpp_params_to_args_conf(int conf)
3007 {
3008 switch (conf) {
3009 case WIFI_DPP_CONF_STA:
3010 return "sta-dpp";
3011 case WIFI_DPP_CONF_AP:
3012 return "ap-dpp";
3013 case WIFI_DPP_CONF_QUERY:
3014 return "query";
3015 default:
3016 return "sta-dpp";
3017 }
3018 }
3019
3020 static const char *dpp_params_to_args_role(int role)
3021 {
3022 switch (role) {
3023 case WIFI_DPP_ROLE_CONFIGURATOR:
3024 return "configurator";
3025 case WIFI_DPP_ROLE_ENROLLEE:
3026 return "enrollee";
3027 case WIFI_DPP_ROLE_EITHER:
3028 return "either";
3029 default:
3030 return "either";
3031 }
3032 }
3033
3034 static void dpp_ssid_bin2str(char *dst, uint8_t *src, int max_len)
3035 {
3036 uint8_t *end = src + strlen(src);
3037
3038 /* do 4 bytes convert first */
3039 for (; (src + 4) < end; src += 4) {
3040 snprintf(dst, max_len, "%02x%02x%02x%02x",
3041 src[0], src[1], src[2], src[3]);
3042 dst += 8;
3043 }
3044
3045 /* then do 1 byte convert */
3046 for (; src < end; src++) {
3047 snprintf(dst, max_len, "%02x", src[0]);
3048 dst += 2;
3049 }
3050 }
3051
3052 #define SUPPLICANT_DPP_CMD_BUF_SIZE 384
3053 #define STR_CUR_TO_END(cur) (cur) = (&(cur)[0] + strlen((cur)))
3054
3055 static int dpp_params_to_cmd(struct wifi_dpp_params *params, char *cmd, size_t max_len)
3056 {
3057 char *pos = cmd;
3058 char *end = cmd + max_len;
3059
3060 switch (params->action) {
3061 case WIFI_DPP_CONFIGURATOR_ADD:
3062 strncpy(pos, "DPP_CONFIGURATOR_ADD", end - pos);
3063 STR_CUR_TO_END(pos);
3064
3065 if (params->configurator_add.curve) {
3066 snprintf(pos, end - pos, " curve=%s",
3067 dpp_params_to_args_curve(params->configurator_add.curve));
3068 STR_CUR_TO_END(pos);
3069 }
3070
3071 if (params->configurator_add.net_access_key_curve) {
3072 snprintf(pos, end - pos, " net_access_key_curve=%s",
3073 dpp_params_to_args_curve(
3074 params->configurator_add.net_access_key_curve));
3075 }
3076 break;
3077 case WIFI_DPP_AUTH_INIT:
3078 strncpy(pos, "DPP_AUTH_INIT", end - pos);
3079 STR_CUR_TO_END(pos);
3080
3081 if (params->auth_init.peer) {
3082 snprintf(pos, end - pos, " peer=%d", params->auth_init.peer);
3083 STR_CUR_TO_END(pos);
3084 }
3085
3086 if (params->auth_init.conf) {
3087 snprintf(pos, end - pos, " conf=%s",
3088 dpp_params_to_args_conf(
3089 params->auth_init.conf));
3090 STR_CUR_TO_END(pos);
3091 }
3092
3093 if (params->auth_init.ssid[0]) {
3094 strncpy(pos, " ssid=", end - pos);
3095 STR_CUR_TO_END(pos);
3096 dpp_ssid_bin2str(pos, params->auth_init.ssid,
3097 WIFI_SSID_MAX_LEN * 2);
3098 STR_CUR_TO_END(pos);
3099 }
3100
3101 if (params->auth_init.configurator) {
3102 snprintf(pos, end - pos, " configurator=%d",
3103 params->auth_init.configurator);
3104 STR_CUR_TO_END(pos);
3105 }
3106
3107 if (params->auth_init.role) {
3108 snprintf(pos, end - pos, " role=%s",
3109 dpp_params_to_args_role(
3110 params->auth_init.role));
3111 }
3112 break;
3113 case WIFI_DPP_QR_CODE:
3114 strncpy(pos, "DPP_QR_CODE", end - pos);
3115 STR_CUR_TO_END(pos);
3116
3117 if (params->dpp_qr_code[0]) {
3118 snprintf(pos, end - pos, " %s", params->dpp_qr_code);
3119 }
3120 break;
3121 case WIFI_DPP_CHIRP:
3122 strncpy(pos, "DPP_CHIRP", end - pos);
3123 STR_CUR_TO_END(pos);
3124
3125 if (params->chirp.id) {
3126 snprintf(pos, end - pos, " own=%d", params->chirp.id);
3127 STR_CUR_TO_END(pos);
3128 }
3129
3130 if (params->chirp.freq) {
3131 snprintf(pos, end - pos, " listen=%d", params->chirp.freq);
3132 }
3133 break;
3134 case WIFI_DPP_LISTEN:
3135 strncpy(pos, "DPP_LISTEN", end - pos);
3136 STR_CUR_TO_END(pos);
3137
3138 if (params->listen.freq) {
3139 snprintf(pos, end - pos, " %d", params->listen.freq);
3140 STR_CUR_TO_END(pos);
3141 }
3142
3143 if (params->listen.role) {
3144 snprintf(pos, end - pos, " role=%s",
3145 dpp_params_to_args_role(
3146 params->listen.role));
3147 }
3148 break;
3149 case WIFI_DPP_BOOTSTRAP_GEN:
3150 strncpy(pos, "DPP_BOOTSTRAP_GEN", end - pos);
3151 STR_CUR_TO_END(pos);
3152
3153 if (params->bootstrap_gen.type) {
3154 strncpy(pos, " type=qrcode", end - pos);
3155 STR_CUR_TO_END(pos);
3156 }
3157
3158 if (params->bootstrap_gen.op_class &&
3159 params->bootstrap_gen.chan) {
3160 snprintf(pos, end - pos, " chan=%d/%d",
3161 params->bootstrap_gen.op_class,
3162 params->bootstrap_gen.chan);
3163 STR_CUR_TO_END(pos);
3164 }
3165
3166 /* mac is mandatory, even if it is zero mac address */
3167 snprintf(pos, end - pos, " mac=%02x:%02x:%02x:%02x:%02x:%02x",
3168 params->bootstrap_gen.mac[0], params->bootstrap_gen.mac[1],
3169 params->bootstrap_gen.mac[2], params->bootstrap_gen.mac[3],
3170 params->bootstrap_gen.mac[4], params->bootstrap_gen.mac[5]);
3171 STR_CUR_TO_END(pos);
3172
3173 if (params->bootstrap_gen.curve) {
3174 snprintf(pos, end - pos, " curve=%s",
3175 dpp_params_to_args_curve(params->bootstrap_gen.curve));
3176 }
3177 break;
3178 case WIFI_DPP_BOOTSTRAP_GET_URI:
3179 snprintf(pos, end - pos, "DPP_BOOTSTRAP_GET_URI %d", params->id);
3180 break;
3181 case WIFI_DPP_SET_CONF_PARAM:
3182 strncpy(pos, "SET dpp_configurator_params", end - pos);
3183 STR_CUR_TO_END(pos);
3184
3185 if (params->configurator_set.peer) {
3186 snprintf(pos, end - pos, " peer=%d", params->configurator_set.peer);
3187 STR_CUR_TO_END(pos);
3188 }
3189
3190 if (params->configurator_set.conf) {
3191 snprintf(pos, end - pos, " conf=%s",
3192 dpp_params_to_args_conf(
3193 params->configurator_set.conf));
3194 STR_CUR_TO_END(pos);
3195 }
3196
3197 if (params->configurator_set.ssid[0]) {
3198 strncpy(pos, " ssid=", end - pos);
3199 STR_CUR_TO_END(pos);
3200 dpp_ssid_bin2str(pos, params->configurator_set.ssid,
3201 WIFI_SSID_MAX_LEN * 2);
3202 STR_CUR_TO_END(pos);
3203 }
3204
3205 if (params->configurator_set.configurator) {
3206 snprintf(pos, end - pos, " configurator=%d",
3207 params->configurator_set.configurator);
3208 STR_CUR_TO_END(pos);
3209 }
3210
3211 if (params->configurator_set.role) {
3212 snprintf(pos, end - pos, " role=%s",
3213 dpp_params_to_args_role(
3214 params->configurator_set.role));
3215 STR_CUR_TO_END(pos);
3216 }
3217
3218 if (params->configurator_set.curve) {
3219 snprintf(pos, end - pos, " curve=%s",
3220 dpp_params_to_args_curve(params->configurator_set.curve));
3221 STR_CUR_TO_END(pos);
3222 }
3223
3224 if (params->configurator_set.net_access_key_curve) {
3225 snprintf(pos, end - pos, " net_access_key_curve=%s",
3226 dpp_params_to_args_curve(
3227 params->configurator_set.net_access_key_curve));
3228 }
3229 break;
3230 case WIFI_DPP_SET_WAIT_RESP_TIME:
3231 snprintf(pos, end - pos, "SET dpp_resp_wait_time %d",
3232 params->dpp_resp_wait_time);
3233 break;
3234 case WIFI_DPP_RECONFIG:
3235 snprintf(pos, end - pos, "DPP_RECONFIG %d", params->network_id);
3236 break;
3237 default:
3238 wpa_printf(MSG_ERROR, "Unknown DPP action");
3239 return -EINVAL;
3240 }
3241
3242 return 0;
3243 }
3244
3245 int supplicant_dpp_dispatch(const struct device *dev, struct wifi_dpp_params *params)
3246 {
3247 int ret;
3248 char *cmd = NULL;
3249
3250 if (params == NULL) {
3251 return -EINVAL;
3252 }
3253
3254 cmd = os_zalloc(SUPPLICANT_DPP_CMD_BUF_SIZE);
3255 if (cmd == NULL) {
3256 return -ENOMEM;
3257 }
3258
3259 /* leave one byte always be 0 */
3260 ret = dpp_params_to_cmd(params, cmd, SUPPLICANT_DPP_CMD_BUF_SIZE - 2);
3261 if (ret) {
3262 os_free(cmd);
3263 return ret;
3264 }
3265
3266 wpa_printf(MSG_DEBUG, "wpa_cli %s", cmd);
3267 if (zephyr_wpa_cli_cmd_resp(cmd, params->resp)) {
3268 os_free(cmd);
3269 return -ENOEXEC;
3270 }
3271
3272 os_free(cmd);
3273 return 0;
3274 }
3275
3276 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
3277 int hapd_dpp_dispatch(const struct device *dev, struct wifi_dpp_params *params)
3278 {
3279 int ret;
3280 char *cmd = NULL;
3281
3282 if (params == NULL) {
3283 return -EINVAL;
3284 }
3285
3286 cmd = os_zalloc(SUPPLICANT_DPP_CMD_BUF_SIZE);
3287 if (cmd == NULL) {
3288 return -ENOMEM;
3289 }
3290
3291 /* leave one byte always be 0 */
3292 ret = dpp_params_to_cmd(params, cmd, SUPPLICANT_DPP_CMD_BUF_SIZE - 2);
3293 if (ret) {
3294 os_free(cmd);
3295 return ret;
3296 }
3297
3298 wpa_printf(MSG_DEBUG, "hostapd_cli %s", cmd);
3299 if (zephyr_hostapd_cli_cmd_resp(cmd, params->resp)) {
3300 os_free(cmd);
3301 return -ENOEXEC;
3302 }
3303
3304 os_free(cmd);
3305 return 0;
3306 }
3307 #endif /* CONFIG_WIFI_NM_HOSTAPD_AP */
3308 #endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP */
3309