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_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
26 #include "eap_peer/eap.h"
27 #endif
28 #include "supp_events.h"
29 #include "hostapd.h"
30 #include "hapd_api.h"
31 #include "wpa_supplicant/bss.h"
32
33 extern struct k_sem wpa_supplicant_ready_sem;
34 extern struct wpa_global *global;
35
36 /* save the last wifi connection parameters */
37 static struct wifi_connect_req_params last_wifi_conn_params;
38
39 enum requested_ops {
40 CONNECT = 0,
41 DISCONNECT,
42 WPS_PBC,
43 WPS_PIN,
44 };
45
46 enum status_thread_state {
47 STATUS_THREAD_STOPPED = 0,
48 STATUS_THREAD_RUNNING,
49 };
50
51 #define OP_STATUS_POLLING_INTERVAL 1
52
53 #define CONNECTION_SUCCESS 0
54 #define CONNECTION_FAILURE 1
55 #define CONNECTION_TERMINATED 2
56
57 #define DISCONNECT_TIMEOUT_MS 5000
58
59 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
60 static struct wifi_enterprise_creds_params enterprise_creds;
61 #endif
62
63 K_MUTEX_DEFINE(wpa_supplicant_mutex);
64
65 extern struct k_work_q *get_workq(void);
66
67 struct wpa_supp_api_ctrl {
68 const struct device *dev;
69 enum requested_ops requested_op;
70 enum status_thread_state status_thread_state;
71 int connection_timeout; /* in seconds */
72 struct k_work_sync sync;
73 bool terminate;
74 };
75
76 static struct wpa_supp_api_ctrl wpas_api_ctrl;
77
78 static void supp_shell_connect_status(struct k_work *work);
79
80 static K_WORK_DELAYABLE_DEFINE(wpa_supp_status_work,
81 supp_shell_connect_status);
82
83 #define wpa_cli_cmd_v(cmd, ...) ({ \
84 bool status; \
85 \
86 if (zephyr_wpa_cli_cmd_v(cmd, ##__VA_ARGS__) < 0) { \
87 wpa_printf(MSG_ERROR, \
88 "Failed to execute wpa_cli command: %s", \
89 cmd); \
90 status = false; \
91 } else { \
92 status = true; \
93 } \
94 \
95 status; \
96 })
97
get_wpa_s_handle(const struct device * dev)98 static struct wpa_supplicant *get_wpa_s_handle(const struct device *dev)
99 {
100 struct net_if *iface = net_if_lookup_by_dev(dev);
101 char if_name[CONFIG_NET_INTERFACE_NAME_LEN + 1];
102 struct wpa_supplicant *wpa_s;
103 int ret;
104
105 if (!iface) {
106 wpa_printf(MSG_ERROR, "Interface for device %s not found", dev->name);
107 return NULL;
108 }
109
110 ret = net_if_get_name(iface, if_name, sizeof(if_name));
111 if (!ret) {
112 wpa_printf(MSG_ERROR, "Cannot get interface name (%d)", ret);
113 return NULL;
114 }
115
116 wpa_s = zephyr_get_handle_by_ifname(if_name);
117 if (!wpa_s) {
118 wpa_printf(MSG_ERROR, "Interface %s not found", if_name);
119 return NULL;
120 }
121
122 return wpa_s;
123 }
124
125 #define WPA_SUPP_STATE_POLLING_MS 10
wait_for_disconnect_complete(const struct device * dev)126 static int wait_for_disconnect_complete(const struct device *dev)
127 {
128 int ret = 0;
129 int attempts = 0;
130 struct wpa_supplicant *wpa_s = get_wpa_s_handle(dev);
131 unsigned int max_attempts = DISCONNECT_TIMEOUT_MS / WPA_SUPP_STATE_POLLING_MS;
132
133 if (!wpa_s) {
134 ret = -ENODEV;
135 wpa_printf(MSG_ERROR, "Failed to get wpa_s handle");
136 goto out;
137 }
138
139 while (wpa_s->wpa_state != WPA_DISCONNECTED) {
140 if (attempts++ > max_attempts) {
141 ret = -ETIMEDOUT;
142 wpa_printf(MSG_WARNING, "Failed to disconnect from network");
143 break;
144 }
145
146 k_sleep(K_MSEC(WPA_SUPP_STATE_POLLING_MS));
147 }
148 out:
149 return ret;
150 }
151
supp_shell_connect_status(struct k_work * work)152 static void supp_shell_connect_status(struct k_work *work)
153 {
154 static int seconds_counter;
155 int status = CONNECTION_SUCCESS;
156 int conn_result = CONNECTION_FAILURE;
157 struct wpa_supplicant *wpa_s;
158 struct wpa_supp_api_ctrl *ctrl = &wpas_api_ctrl;
159
160 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
161
162 if (ctrl->status_thread_state == STATUS_THREAD_RUNNING && ctrl->terminate) {
163 status = CONNECTION_TERMINATED;
164 goto out;
165 }
166
167 wpa_s = get_wpa_s_handle(ctrl->dev);
168 if (!wpa_s) {
169 status = CONNECTION_FAILURE;
170 goto out;
171 }
172
173 if (ctrl->requested_op == CONNECT && wpa_s->wpa_state != WPA_COMPLETED) {
174 if (ctrl->connection_timeout > 0 &&
175 seconds_counter++ > ctrl->connection_timeout) {
176 if (!wpa_cli_cmd_v("disconnect")) {
177 goto out;
178 }
179
180 conn_result = -ETIMEDOUT;
181 supplicant_send_wifi_mgmt_event(wpa_s->ifname,
182 NET_EVENT_WIFI_CMD_CONNECT_RESULT,
183 (void *)&conn_result, sizeof(int));
184 status = CONNECTION_FAILURE;
185 goto out;
186 }
187
188 k_work_reschedule_for_queue(get_workq(), &wpa_supp_status_work,
189 K_SECONDS(OP_STATUS_POLLING_INTERVAL));
190 ctrl->status_thread_state = STATUS_THREAD_RUNNING;
191 k_mutex_unlock(&wpa_supplicant_mutex);
192 return;
193 }
194 out:
195 seconds_counter = 0;
196
197 ctrl->status_thread_state = STATUS_THREAD_STOPPED;
198 k_mutex_unlock(&wpa_supplicant_mutex);
199 }
200
get_mode_by_band(struct wpa_supplicant * wpa_s,uint8_t band)201 static struct hostapd_hw_modes *get_mode_by_band(struct wpa_supplicant *wpa_s, uint8_t band)
202 {
203 enum hostapd_hw_mode hw_mode;
204 bool is_6ghz = (band == WIFI_FREQ_BAND_6_GHZ) ? true : false;
205
206 if (band == WIFI_FREQ_BAND_2_4_GHZ) {
207 hw_mode = HOSTAPD_MODE_IEEE80211G;
208 } else if ((band == WIFI_FREQ_BAND_5_GHZ) ||
209 (band == WIFI_FREQ_BAND_6_GHZ)) {
210 hw_mode = HOSTAPD_MODE_IEEE80211A;
211 } else {
212 return NULL;
213 }
214
215 return get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, is_6ghz);
216 }
217
wpa_supp_supported_channels(struct wpa_supplicant * wpa_s,uint8_t band,char ** chan_list)218 static int wpa_supp_supported_channels(struct wpa_supplicant *wpa_s, uint8_t band, char **chan_list)
219 {
220 struct hostapd_hw_modes *mode = NULL;
221 int i;
222 int offset, retval;
223 int size;
224 char *_chan_list;
225
226 mode = get_mode_by_band(wpa_s, band);
227 if (!mode) {
228 wpa_printf(MSG_ERROR, "Unsupported or invalid band: %d", band);
229 return -EINVAL;
230 }
231
232 size = ((mode->num_channels) * CHAN_NUM_LEN) + 1;
233 _chan_list = os_malloc(size);
234 if (!_chan_list) {
235 wpa_printf(MSG_ERROR, "Mem alloc failed for channel list");
236 return -ENOMEM;
237 }
238
239 retval = 0;
240 offset = 0;
241 for (i = 0; i < mode->num_channels; i++) {
242 retval = snprintf(_chan_list + offset, CHAN_NUM_LEN, " %d",
243 mode->channels[i].freq);
244 offset += retval;
245 }
246 *chan_list = _chan_list;
247
248 return 0;
249 }
250
wpa_supp_band_chan_compat(struct wpa_supplicant * wpa_s,uint8_t band,uint8_t channel)251 static int wpa_supp_band_chan_compat(struct wpa_supplicant *wpa_s, uint8_t band, uint8_t channel)
252 {
253 struct hostapd_hw_modes *mode = NULL;
254 int i;
255
256 mode = get_mode_by_band(wpa_s, band);
257 if (!mode) {
258 wpa_printf(MSG_ERROR, "Unsupported or invalid band: %d", band);
259 return -EINVAL;
260 }
261
262 for (i = 0; i < mode->num_channels; i++) {
263 if (mode->channels[i].chan == channel) {
264 return mode->channels[i].freq;
265 }
266 }
267
268 wpa_printf(MSG_ERROR, "Channel %d not supported for band %d", channel, band);
269
270 return -EINVAL;
271 }
272
wpa_supp_restart_status_work(void)273 static inline void wpa_supp_restart_status_work(void)
274 {
275 /* Terminate synchronously */
276 wpas_api_ctrl.terminate = 1;
277 k_work_flush_delayable(&wpa_supp_status_work, &wpas_api_ctrl.sync);
278 wpas_api_ctrl.terminate = 0;
279
280 /* Start afresh */
281 k_work_reschedule_for_queue(get_workq(), &wpa_supp_status_work, K_MSEC(10));
282 }
283
chan_to_freq(int chan)284 static inline int chan_to_freq(int chan)
285 {
286 /* We use global channel list here and also use the widest
287 * op_class for 5GHz channels as there is no user input
288 * for these (yet).
289 */
290 int freq = -1;
291 int op_classes[] = {81, 82, 128};
292 int op_classes_size = ARRAY_SIZE(op_classes);
293
294 for (int i = 0; i < op_classes_size; i++) {
295 freq = ieee80211_chan_to_freq(NULL, op_classes[i], chan);
296 if (freq > 0) {
297 break;
298 }
299 }
300
301 if (freq <= 0) {
302 wpa_printf(MSG_ERROR, "Invalid channel %d", chan);
303 return -1;
304 }
305
306 return freq;
307 }
308
wpas_band_to_zephyr(enum wpa_radio_work_band band)309 enum wifi_frequency_bands wpas_band_to_zephyr(enum wpa_radio_work_band band)
310 {
311 switch (band) {
312 case BAND_2_4_GHZ:
313 return WIFI_FREQ_BAND_2_4_GHZ;
314 case BAND_5_GHZ:
315 return WIFI_FREQ_BAND_5_GHZ;
316 default:
317 return WIFI_FREQ_BAND_UNKNOWN;
318 }
319 }
320
wpas_key_mgmt_to_zephyr_wpa3_ent(int key_mgmt)321 enum wifi_wpa3_enterprise_type wpas_key_mgmt_to_zephyr_wpa3_ent(int key_mgmt)
322 {
323 switch (key_mgmt) {
324 case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
325 return WIFI_WPA3_ENTERPRISE_SUITEB;
326 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
327 return WIFI_WPA3_ENTERPRISE_SUITEB_192;
328 case WPA_KEY_MGMT_IEEE8021X_SHA256:
329 return WIFI_WPA3_ENTERPRISE_ONLY;
330 default:
331 return WIFI_WPA3_ENTERPRISE_NA;
332 }
333 }
334
wpas_key_mgmt_to_zephyr(bool is_hapd,void * config,int key_mgmt,int proto,int pwe)335 enum wifi_security_type wpas_key_mgmt_to_zephyr(bool is_hapd, void *config, int key_mgmt,
336 int proto, int pwe)
337 {
338 switch (key_mgmt) {
339 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
340 case WPA_KEY_MGMT_IEEE8021X:
341 case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
342 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
343 case WPA_KEY_MGMT_IEEE8021X_SHA256:
344 if (is_hapd) {
345 #ifdef CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE
346 struct hostapd_bss_config *conf = (struct hostapd_bss_config *)config;
347
348 switch (conf->eap_user->methods[0].method) {
349 case WIFI_EAP_TYPE_PEAP:
350 if (conf->eap_user->next && conf->eap_user->next->phase2) {
351 switch (conf->eap_user->next->methods[0].method) {
352 case WIFI_EAP_TYPE_MSCHAPV2:
353 return WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2;
354 case WIFI_EAP_TYPE_GTC:
355 return WIFI_SECURITY_TYPE_EAP_PEAP_GTC;
356 case WIFI_EAP_TYPE_TLS:
357 return WIFI_SECURITY_TYPE_EAP_PEAP_TLS;
358 }
359 }
360 case WIFI_EAP_TYPE_TTLS:
361 if (conf->eap_user->next && conf->eap_user->next->phase2) {
362 if (conf->eap_user->next->ttls_auth & 0x1E) {
363 return WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2;
364 }
365 }
366 }
367 #endif
368 } else {
369 struct wpa_ssid *ssid = (struct wpa_ssid *)config;
370
371 switch (ssid->eap.eap_methods->method) {
372 case WIFI_EAP_TYPE_TTLS:
373 if (!os_memcmp(ssid->eap.phase2, "auth=MSCHAPV2",
374 os_strlen(ssid->eap.phase2))) {
375 return WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2;
376 }
377 case WIFI_EAP_TYPE_PEAP:
378 if (!os_memcmp(ssid->eap.phase2, "auth=MSCHAPV2",
379 os_strlen(ssid->eap.phase2))) {
380 return WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2;
381 } else if (!os_memcmp(ssid->eap.phase2, "auth=GTC",
382 os_strlen(ssid->eap.phase2))) {
383 return WIFI_SECURITY_TYPE_EAP_PEAP_GTC;
384 } else if (!os_memcmp(ssid->eap.phase2, "auth=TLS",
385 os_strlen(ssid->eap.phase2))) {
386 return WIFI_SECURITY_TYPE_EAP_PEAP_TLS;
387 }
388 }
389 }
390 return WIFI_SECURITY_TYPE_EAP_TLS;
391 #endif
392 case WPA_KEY_MGMT_NONE:
393 return WIFI_SECURITY_TYPE_NONE;
394 case WPA_KEY_MGMT_PSK:
395 if (proto == WPA_PROTO_RSN) {
396 return WIFI_SECURITY_TYPE_PSK;
397 } else {
398 return WIFI_SECURITY_TYPE_WPA_PSK;
399 }
400 case WPA_KEY_MGMT_PSK_SHA256:
401 return WIFI_SECURITY_TYPE_PSK_SHA256;
402 case WPA_KEY_MGMT_SAE:
403 if (pwe == 1) {
404 return WIFI_SECURITY_TYPE_SAE_H2E;
405 } else if (pwe == 2) {
406 return WIFI_SECURITY_TYPE_SAE_AUTO;
407 } else {
408 return WIFI_SECURITY_TYPE_SAE_HNP;
409 }
410 case WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK:
411 return WIFI_SECURITY_TYPE_WPA_AUTO_PERSONAL;
412 case WPA_KEY_MGMT_FT_PSK:
413 return WIFI_SECURITY_TYPE_FT_PSK;
414 case WPA_KEY_MGMT_FT_SAE:
415 return WIFI_SECURITY_TYPE_FT_SAE;
416 case WPA_KEY_MGMT_FT_IEEE8021X:
417 return WIFI_SECURITY_TYPE_FT_EAP;
418 case WPA_KEY_MGMT_DPP:
419 return WIFI_SECURITY_TYPE_DPP;
420 case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
421 return WIFI_SECURITY_TYPE_FT_EAP_SHA384;
422 case WPA_KEY_MGMT_SAE_EXT_KEY:
423 return WIFI_SECURITY_TYPE_SAE_EXT_KEY;
424 case WPA_KEY_MGMT_DPP | WPA_KEY_MGMT_PSK:
425 return WIFI_SECURITY_TYPE_DPP;
426 default:
427 return WIFI_SECURITY_TYPE_UNKNOWN;
428 }
429 }
430
431 #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)432 static int wpas_config_process_blob(struct wpa_config *config, char *name, uint8_t *data,
433 uint32_t data_len)
434 {
435 struct wpa_config_blob *blob;
436
437 if (!data || !data_len) {
438 return -1;
439 }
440
441 blob = os_zalloc(sizeof(*blob));
442 if (blob == NULL) {
443 return -1;
444 }
445
446 blob->data = os_zalloc(data_len);
447 if (blob->data == NULL) {
448 os_free(blob);
449 return -1;
450 }
451
452 blob->name = os_strdup(name);
453
454 if (blob->name == NULL) {
455 wpa_config_free_blob(blob);
456 return -1;
457 }
458
459 os_memcpy(blob->data, data, data_len);
460 blob->len = data_len;
461
462 wpa_config_set_blob(config, blob);
463
464 return 0;
465 }
466 #endif
467
468 #if defined CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE || \
469 defined CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE
supplicant_add_enterprise_creds(const struct device * dev,struct wifi_enterprise_creds_params * creds)470 int supplicant_add_enterprise_creds(const struct device *dev,
471 struct wifi_enterprise_creds_params *creds)
472 {
473 int ret = 0;
474
475 if (!creds) {
476 ret = -1;
477 wpa_printf(MSG_ERROR, "enterprise creds is NULL");
478 goto out;
479 }
480
481 memcpy((void *)&enterprise_creds, (void *)creds,
482 sizeof(struct wifi_enterprise_creds_params));
483
484 out:
485 return ret;
486 }
487
488 static const struct wifi_cipher_desc ciphers[] = {
489 {WPA_CAPA_ENC_GCMP_256, "GCMP-256"},
490 {WPA_CAPA_ENC_CCMP, "CCMP"},
491 {WPA_CAPA_ENC_GCMP, "GCMP"},
492 };
493
494 static const struct wifi_cipher_desc ciphers_group_mgmt[] = {
495 {WPA_CAPA_ENC_BIP, "AES-128-CMAC"},
496 {WPA_CAPA_ENC_BIP_GMAC_128, "BIP-GMAC-128"},
497 {WPA_CAPA_ENC_BIP_GMAC_256, "BIP-GMAC-256"},
498 };
499
500 static struct wifi_eap_config eap_config[] = {
501 {WIFI_SECURITY_TYPE_EAP_TLS, WIFI_EAP_TYPE_TLS, WIFI_EAP_TYPE_NONE, "TLS", NULL},
502 {WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2, WIFI_EAP_TYPE_PEAP, WIFI_EAP_TYPE_MSCHAPV2, "PEAP",
503 "auth=MSCHAPV2"},
504 {WIFI_SECURITY_TYPE_EAP_PEAP_GTC, WIFI_EAP_TYPE_PEAP, WIFI_EAP_TYPE_GTC, "PEAP",
505 "auth=GTC"},
506 {WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2, WIFI_EAP_TYPE_TTLS, WIFI_EAP_TYPE_NONE, "TTLS",
507 "auth=MSCHAPV2"},
508 {WIFI_SECURITY_TYPE_EAP_PEAP_TLS, WIFI_EAP_TYPE_PEAP, WIFI_EAP_TYPE_TLS, "PEAP",
509 "auth=TLS"},
510 };
511
process_cipher_config(struct wifi_connect_req_params * params,struct wifi_eap_cipher_config * cipher_config)512 int process_cipher_config(struct wifi_connect_req_params *params,
513 struct wifi_eap_cipher_config *cipher_config)
514 {
515 unsigned int cipher_capa;
516 unsigned int gropu_mgmt_cipher_capa;
517 unsigned int index;
518
519 if (params->wpa3_ent_mode == WIFI_WPA3_ENTERPRISE_SUITEB) {
520 cipher_capa = WPA_CAPA_ENC_GCMP;
521 gropu_mgmt_cipher_capa = WPA_CAPA_ENC_BIP_GMAC_128;
522 cipher_config->key_mgmt = "WPA-EAP-SUITE-B";
523 cipher_config->openssl_ciphers = "SUITEB128";
524 cipher_config->tls_flags = "[SUITEB]";
525 } else if (params->wpa3_ent_mode == WIFI_WPA3_ENTERPRISE_SUITEB_192) {
526 cipher_capa = WPA_CAPA_ENC_GCMP_256;
527 gropu_mgmt_cipher_capa = WPA_CAPA_ENC_BIP_GMAC_256;
528 if (params->ft_used) {
529 cipher_config->key_mgmt = "WPA-EAP-SUITE-B-192 FT-EAP-SHA384";
530 } else {
531 cipher_config->key_mgmt = "WPA-EAP-SUITE-B-192";
532 }
533 cipher_config->openssl_ciphers = "SUITEB192";
534 cipher_config->tls_flags = "[SUITEB]";
535 } else if (params->wpa3_ent_mode == WIFI_WPA3_ENTERPRISE_ONLY) {
536 cipher_capa = WPA_CAPA_ENC_CCMP;
537 gropu_mgmt_cipher_capa = WPA_CAPA_ENC_BIP;
538 cipher_config->key_mgmt = "WPA-EAP-SHA256";
539 } else {
540 cipher_capa = WPA_CAPA_ENC_CCMP;
541 gropu_mgmt_cipher_capa = WPA_CAPA_ENC_BIP;
542 if (params->ft_used) {
543 cipher_config->key_mgmt = "WPA-EAP FT-EAP";
544 } else {
545 cipher_config->key_mgmt = "WPA-EAP";
546 }
547 }
548
549 for (index = 0; index < ARRAY_SIZE(ciphers); index++) {
550 if (cipher_capa == ciphers[index].capa) {
551 cipher_config->group_cipher = ciphers[index].name;
552 cipher_config->pairwise_cipher = ciphers[index].name;
553 break;
554 }
555 }
556
557 if (index == ARRAY_SIZE(ciphers)) {
558 wpa_printf(MSG_ERROR, "Get ciphers error");
559 goto out;
560 }
561
562 for (index = 0; index < ARRAY_SIZE(ciphers_group_mgmt); index++) {
563 if (gropu_mgmt_cipher_capa == ciphers_group_mgmt[index].capa) {
564 cipher_config->group_mgmt_cipher = ciphers_group_mgmt[index].name;
565 break;
566 }
567 }
568
569 if (index == ARRAY_SIZE(ciphers_group_mgmt)) {
570 wpa_printf(MSG_ERROR, "Get group mgmt ciphers error");
571 goto out;
572 }
573
574 return 0;
575 out:
576 return -EINVAL;
577 }
578
is_eap_valid_security(int security)579 int is_eap_valid_security(int security)
580 {
581 return (security == WIFI_SECURITY_TYPE_EAP_TLS ||
582 security == WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2 ||
583 security == WIFI_SECURITY_TYPE_EAP_PEAP_GTC ||
584 security == WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2 ||
585 security == WIFI_SECURITY_TYPE_EAP_PEAP_TLS);
586 }
587 #endif
588
589 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
wpas_remove_certs(struct wpa_supplicant * wpa_s)590 static void wpas_remove_certs(struct wpa_supplicant *wpa_s)
591 {
592 wpa_config_remove_blob(wpa_s->conf, "ca_cert");
593 wpa_config_remove_blob(wpa_s->conf, "client_cert");
594 wpa_config_remove_blob(wpa_s->conf, "private_key");
595 wpa_config_remove_blob(wpa_s->conf, "ca_cert2");
596 wpa_config_remove_blob(wpa_s->conf, "client_cert2");
597 wpa_config_remove_blob(wpa_s->conf, "private_key2");
598 }
599 #endif
600
wpas_add_and_config_network(struct wpa_supplicant * wpa_s,struct wifi_connect_req_params * params,bool mode_ap)601 static int wpas_add_and_config_network(struct wpa_supplicant *wpa_s,
602 struct wifi_connect_req_params *params,
603 bool mode_ap)
604 {
605 struct add_network_resp resp = {0};
606 char *chan_list = NULL;
607 struct net_eth_addr mac = {0};
608 int ret = 0;
609 uint8_t ssid_null_terminated[WIFI_SSID_MAX_LEN + 1];
610 uint8_t psk_null_terminated[WIFI_PSK_MAX_LEN + 1];
611 uint8_t sae_null_terminated[WIFI_SAE_PSWD_MAX_LEN + 1];
612 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
613 struct wifi_eap_cipher_config cipher_config = {NULL, "DEFAULT:!EXP:!LOW", "CCMP",
614 "CCMP", "AES-128-CMAC", NULL};
615 char *method = NULL;
616 char phase1[128] = {0};
617 char *phase2 = NULL;
618 unsigned int index;
619
620 wpas_remove_certs(wpa_s);
621 #endif
622
623 if (!wpa_cli_cmd_v("remove_network all")) {
624 goto out;
625 }
626
627 ret = z_wpa_ctrl_add_network(&resp);
628 if (ret) {
629 wpa_printf(MSG_ERROR, "Failed to add network");
630 goto out;
631 }
632
633 wpa_printf(MSG_DEBUG, "NET added: %d", resp.network_id);
634
635 if (mode_ap) {
636 if (!wpa_cli_cmd_v("set_network %d mode 2", resp.network_id)) {
637 goto out;
638 }
639 }
640
641 if (params->ssid_length > WIFI_SSID_MAX_LEN) {
642 wpa_printf(MSG_ERROR, "SSID too long (max %d characters)", WIFI_SSID_MAX_LEN);
643 goto out;
644 }
645
646 strncpy(ssid_null_terminated, params->ssid, WIFI_SSID_MAX_LEN);
647 ssid_null_terminated[params->ssid_length] = '\0';
648
649 if (!wpa_cli_cmd_v("set_network %d ssid \"%s\"",
650 resp.network_id, ssid_null_terminated)) {
651 goto out;
652 }
653
654 if (!wpa_cli_cmd_v("set_network %d scan_ssid 1", resp.network_id)) {
655 goto out;
656 }
657
658 if (!wpa_cli_cmd_v("set_network %d key_mgmt NONE", resp.network_id)) {
659 goto out;
660 }
661
662 if (!wpa_cli_cmd_v("set_network %d ieee80211w 0", resp.network_id)) {
663 goto out;
664 }
665
666 if (params->band != WIFI_FREQ_BAND_UNKNOWN) {
667 ret = wpa_supp_supported_channels(wpa_s, params->band, &chan_list);
668 if (ret < 0) {
669 goto rem_net;
670 }
671
672 if (chan_list) {
673 if (!wpa_cli_cmd_v("set_network %d scan_freq%s", resp.network_id,
674 chan_list)) {
675 os_free(chan_list);
676 goto out;
677 }
678
679 os_free(chan_list);
680 }
681 }
682
683 if (params->security != WIFI_SECURITY_TYPE_NONE) {
684 if (params->psk) {
685 if ((params->psk_length < WIFI_PSK_MIN_LEN) ||
686 (params->psk_length > WIFI_PSK_MAX_LEN)) {
687 wpa_printf(MSG_ERROR,
688 "Passphrase should be in range (%d-%d) characters",
689 WIFI_PSK_MIN_LEN, WIFI_PSK_MAX_LEN);
690 goto out;
691 }
692 strncpy(psk_null_terminated, params->psk, WIFI_PSK_MAX_LEN);
693 psk_null_terminated[params->psk_length] = '\0';
694 }
695
696 /* SAP - only open and WPA2-PSK are supported for now */
697 if (mode_ap && params->security != WIFI_SECURITY_TYPE_PSK) {
698 ret = -1;
699 wpa_printf(MSG_ERROR, "Unsupported security type: %d",
700 params->security);
701 goto rem_net;
702 }
703
704 /* Except for WPA-PSK, rest all are under WPA2 */
705 if (params->security != WIFI_SECURITY_TYPE_WPA_PSK) {
706 if (!wpa_cli_cmd_v("set_network %d proto RSN",
707 resp.network_id)) {
708 goto out;
709 }
710 }
711
712 if (params->security == WIFI_SECURITY_TYPE_SAE_HNP ||
713 params->security == WIFI_SECURITY_TYPE_SAE_H2E ||
714 params->security == WIFI_SECURITY_TYPE_SAE_AUTO ||
715 params->security == WIFI_SECURITY_TYPE_SAE_EXT_KEY) {
716 if (params->sae_password) {
717 if ((params->sae_password_length < WIFI_PSK_MIN_LEN) ||
718 (params->sae_password_length > WIFI_SAE_PSWD_MAX_LEN)) {
719 wpa_printf(MSG_ERROR,
720 "Passphrase should be in range (%d-%d) characters",
721 WIFI_PSK_MIN_LEN, WIFI_SAE_PSWD_MAX_LEN);
722 goto out;
723 }
724 strncpy(sae_null_terminated, params->sae_password,
725 WIFI_SAE_PSWD_MAX_LEN);
726 sae_null_terminated[params->sae_password_length] = '\0';
727 if (!wpa_cli_cmd_v("set_network %d sae_password \"%s\"",
728 resp.network_id, sae_null_terminated)) {
729 goto out;
730 }
731 } else {
732 if (!wpa_cli_cmd_v("set_network %d sae_password \"%s\"",
733 resp.network_id, psk_null_terminated)) {
734 goto out;
735 }
736 }
737
738 if (!wpa_cli_cmd_v("set sae_pwe %d",
739 (params->security == WIFI_SECURITY_TYPE_SAE_H2E)
740 ? 1
741 : ((params->security == WIFI_SECURITY_TYPE_SAE_HNP)
742 ? 0
743 : 2))) {
744 goto out;
745 }
746
747 if (params->security != WIFI_SECURITY_TYPE_SAE_EXT_KEY) {
748 if (!wpa_cli_cmd_v("set_network %d key_mgmt SAE%s", resp.network_id,
749 params->ft_used ? " FT-SAE" : "")) {
750 goto out;
751 }
752 } else {
753 if (!wpa_cli_cmd_v("set_network %d key_mgmt SAE-EXT-KEY%s",
754 resp.network_id,
755 params->ft_used ? " FT-SAE-EXT-KEY" : "")) {
756 goto out;
757 }
758 }
759
760 if (!wpa_cli_cmd_v("set_network %d group CCMP", resp.network_id)) {
761 goto out;
762 }
763
764 if (!wpa_cli_cmd_v("set_network %d pairwise CCMP", resp.network_id)) {
765 goto out;
766 }
767 } else if (params->security == WIFI_SECURITY_TYPE_PSK_SHA256) {
768 if (!wpa_cli_cmd_v("set_network %d psk \"%s\"",
769 resp.network_id, psk_null_terminated)) {
770 goto out;
771 }
772
773 if (!wpa_cli_cmd_v("set_network %d key_mgmt WPA-PSK-SHA256",
774 resp.network_id)) {
775 goto out;
776 }
777
778 if (!wpa_cli_cmd_v("set_network %d group CCMP", resp.network_id)) {
779 goto out;
780 }
781
782 if (!wpa_cli_cmd_v("set_network %d pairwise CCMP", resp.network_id)) {
783 goto out;
784 }
785 } else if (params->security == WIFI_SECURITY_TYPE_PSK ||
786 params->security == WIFI_SECURITY_TYPE_WPA_PSK) {
787 if (!wpa_cli_cmd_v("set_network %d psk \"%s\"",
788 resp.network_id, psk_null_terminated)) {
789 goto out;
790 }
791
792 if (!wpa_cli_cmd_v("set_network %d key_mgmt WPA-PSK%s",
793 resp.network_id, params->ft_used ? " FT-PSK" : "")) {
794 goto out;
795 }
796
797 if (params->security == WIFI_SECURITY_TYPE_WPA_PSK) {
798 if (!wpa_cli_cmd_v("set_network %d proto WPA",
799 resp.network_id)) {
800 goto out;
801 }
802 } else {
803 if (!wpa_cli_cmd_v("set_network %d group CCMP", resp.network_id)) {
804 goto out;
805 }
806
807 if (!wpa_cli_cmd_v("set_network %d pairwise CCMP",
808 resp.network_id)) {
809 goto out;
810 }
811 }
812 } else if (params->security == WIFI_SECURITY_TYPE_WPA_AUTO_PERSONAL) {
813 if (!wpa_cli_cmd_v("set_network %d psk \"%s\"", resp.network_id,
814 psk_null_terminated)) {
815 goto out;
816 }
817
818 if (params->sae_password) {
819 if (!wpa_cli_cmd_v("set_network %d sae_password \"%s\"",
820 resp.network_id, sae_null_terminated)) {
821 goto out;
822 }
823 } else {
824 if (!wpa_cli_cmd_v("set_network %d sae_password \"%s\"",
825 resp.network_id, psk_null_terminated)) {
826 goto out;
827 }
828 }
829
830 if (!wpa_cli_cmd_v("set sae_pwe 2")) {
831 goto out;
832 }
833
834 if (!wpa_cli_cmd_v("set_network %d key_mgmt WPA-PSK SAE",
835 resp.network_id)) {
836 goto out;
837 }
838
839 if (!wpa_cli_cmd_v("set_network %d group CCMP", resp.network_id)) {
840 goto out;
841 }
842
843 if (!wpa_cli_cmd_v("set_network %d pairwise CCMP", resp.network_id)) {
844 goto out;
845 }
846 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
847 } else if (is_eap_valid_security(params->security)) {
848 if (process_cipher_config(params, &cipher_config)) {
849 goto out;
850 }
851
852 for (index = 0; index < ARRAY_SIZE(eap_config); index++) {
853 if (params->security == eap_config[index].type) {
854 method = eap_config[index].method;
855 phase2 = eap_config[index].phase2;
856 break;
857 }
858 }
859
860 if (index == ARRAY_SIZE(eap_config)) {
861 wpa_printf(MSG_ERROR, "Get eap method error with security type: %d",
862 params->security);
863 goto out;
864 }
865
866 if (params->wpa3_ent_mode == WIFI_WPA3_ENTERPRISE_SUITEB_192) {
867 if (params->TLS_cipher == WIFI_EAP_TLS_ECC_P384) {
868 if (!wpa_cli_cmd_v("set_network %d openssl_ciphers \"%s\"",
869 resp.network_id,
870 cipher_config.openssl_ciphers)) {
871 goto out;
872 }
873 } else if (params->TLS_cipher == WIFI_EAP_TLS_RSA_3K) {
874 snprintf(phase1, sizeof(phase1), "tls_suiteb=1");
875 if (!wpa_cli_cmd_v("set_network %d phase1 \"%s\"",
876 resp.network_id, &phase1[0])) {
877 goto out;
878 }
879 }
880 }
881
882 if (!wpa_cli_cmd_v("set_network %d key_mgmt %s", resp.network_id,
883 cipher_config.key_mgmt)) {
884 goto out;
885 }
886
887 if (!wpa_cli_cmd_v("set openssl_ciphers \"%s\"",
888 cipher_config.openssl_ciphers)) {
889 goto out;
890 }
891
892 if (!wpa_cli_cmd_v("set_network %d group %s", resp.network_id,
893 cipher_config.group_cipher)) {
894 goto out;
895 }
896
897 if (!wpa_cli_cmd_v("set_network %d pairwise %s", resp.network_id,
898 cipher_config.pairwise_cipher)) {
899 goto out;
900 }
901
902 if (!wpa_cli_cmd_v("set_network %d group_mgmt %s", resp.network_id,
903 cipher_config.group_mgmt_cipher)) {
904 goto out;
905 }
906
907 if (!wpa_cli_cmd_v("set_network %d proto RSN",
908 resp.network_id)) {
909 goto out;
910 }
911
912 if (method != NULL) {
913 if (!wpa_cli_cmd_v("set_network %d eap %s", resp.network_id,
914 method)) {
915 goto out;
916 }
917 }
918
919 if (params->security == WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2 ||
920 params->security == WIFI_SECURITY_TYPE_EAP_PEAP_GTC ||
921 params->security == WIFI_SECURITY_TYPE_EAP_PEAP_TLS) {
922 snprintk(phase1, sizeof(phase1),
923 "peapver=%d peaplabel=0 crypto_binding=0",
924 params->eap_ver);
925
926 if (!wpa_cli_cmd_v("set_network %d phase1 \"%s\"", resp.network_id,
927 &phase1[0])) {
928 goto out;
929 }
930 }
931
932 if (phase2 != NULL) {
933 if (!wpa_cli_cmd_v("set_network %d phase2 \"%s\"", resp.network_id,
934 phase2)) {
935 goto out;
936 }
937 }
938
939 if (params->eap_id_length > 0) {
940 if (!wpa_cli_cmd_v("set_network %d identity \"%s\"",
941 resp.network_id, params->eap_identity)) {
942 goto out;
943 }
944 }
945
946 if (params->eap_passwd_length > 0) {
947 if (!wpa_cli_cmd_v("set_network %d password \"%s\"",
948 resp.network_id, params->eap_password)) {
949 goto out;
950 }
951 }
952
953 if (!wpa_cli_cmd_v("set_network %d anonymous_identity \"%s\"",
954 resp.network_id, params->anon_id)) {
955 goto out;
956 }
957
958 if (false == ((params->security == WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2 ||
959 params->security == WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2) &&
960 (!params->verify_peer_cert))) {
961 if (wpas_config_process_blob(wpa_s->conf, "ca_cert",
962 enterprise_creds.ca_cert,
963 enterprise_creds.ca_cert_len)) {
964 goto out;
965 }
966
967 if (!wpa_cli_cmd_v("set_network %d ca_cert \"blob://ca_cert\"",
968 resp.network_id)) {
969 goto out;
970 }
971 }
972
973 if (wpas_config_process_blob(wpa_s->conf, "client_cert",
974 enterprise_creds.client_cert,
975 enterprise_creds.client_cert_len)) {
976 goto out;
977 }
978
979 if (!wpa_cli_cmd_v("set_network %d client_cert \"blob://client_cert\"",
980 resp.network_id)) {
981 goto out;
982 }
983
984 if (wpas_config_process_blob(wpa_s->conf, "private_key",
985 enterprise_creds.client_key,
986 enterprise_creds.client_key_len)) {
987 goto out;
988 }
989
990 if (!wpa_cli_cmd_v("set_network %d private_key \"blob://private_key\"",
991 resp.network_id)) {
992 goto out;
993 }
994
995 if (!wpa_cli_cmd_v("set_network %d private_key_passwd \"%s\"",
996 resp.network_id, params->key_passwd)) {
997 goto out;
998 }
999
1000 if (wpas_config_process_blob(wpa_s->conf, "ca_cert2",
1001 enterprise_creds.ca_cert2,
1002 enterprise_creds.ca_cert2_len)) {
1003 goto out;
1004 }
1005
1006 if (!wpa_cli_cmd_v("set_network %d ca_cert2 \"blob://ca_cert2\"",
1007 resp.network_id)) {
1008 goto out;
1009 }
1010
1011 if (wpas_config_process_blob(wpa_s->conf, "client_cert2",
1012 enterprise_creds.client_cert2,
1013 enterprise_creds.client_cert2_len)) {
1014 goto out;
1015 }
1016
1017 if (!wpa_cli_cmd_v("set_network %d client_cert2 \"blob://client_cert2\"",
1018 resp.network_id)) {
1019 goto out;
1020 }
1021
1022 if (wpas_config_process_blob(wpa_s->conf, "private_key2",
1023 enterprise_creds.client_key2,
1024 enterprise_creds.client_key2_len)) {
1025 goto out;
1026 }
1027
1028 if (!wpa_cli_cmd_v("set_network %d private_key2 \"blob://private_key2\"",
1029 resp.network_id)) {
1030 goto out;
1031 }
1032
1033 if (!wpa_cli_cmd_v("set_network %d private_key2_passwd \"%s\"",
1034 resp.network_id, params->key2_passwd)) {
1035 goto out;
1036 }
1037 #endif
1038 } else {
1039 ret = -1;
1040 wpa_printf(MSG_ERROR, "Unsupported security type: %d",
1041 params->security);
1042 goto rem_net;
1043 }
1044
1045 if (params->mfp) {
1046 if (!wpa_cli_cmd_v("set_network %d ieee80211w %d",
1047 resp.network_id, params->mfp)) {
1048 goto out;
1049 }
1050 }
1051 }
1052
1053 if (params->channel != WIFI_CHANNEL_ANY) {
1054 int freq;
1055
1056 if (params->band != WIFI_FREQ_BAND_UNKNOWN) {
1057 freq = wpa_supp_band_chan_compat(wpa_s, params->band, params->channel);
1058 if (freq < 0) {
1059 goto rem_net;
1060 }
1061 } else {
1062 freq = chan_to_freq(params->channel);
1063 if (freq < 0) {
1064 ret = -1;
1065 wpa_printf(MSG_ERROR, "Invalid channel %d",
1066 params->channel);
1067 goto rem_net;
1068 }
1069 }
1070
1071 if (mode_ap) {
1072 if (!wpa_cli_cmd_v("set_network %d frequency %d",
1073 resp.network_id, freq)) {
1074 goto out;
1075 }
1076 } else {
1077 if (!wpa_cli_cmd_v("set_network %d scan_freq %d",
1078 resp.network_id, freq)) {
1079 goto out;
1080 }
1081 }
1082 }
1083
1084 memcpy((void *)&mac, params->bssid, WIFI_MAC_ADDR_LEN);
1085 if (net_eth_is_addr_broadcast(&mac) ||
1086 net_eth_is_addr_multicast(&mac)) {
1087 wpa_printf(MSG_ERROR, "Invalid BSSID. Configuration "
1088 "of multicast or broadcast MAC is not allowed.");
1089 ret = -EINVAL;
1090 goto rem_net;
1091 }
1092
1093 if (!net_eth_is_addr_unspecified(&mac)) {
1094 char bssid_str[MAC_STR_LEN] = {0};
1095
1096 snprintf(bssid_str, MAC_STR_LEN, "%02x:%02x:%02x:%02x:%02x:%02x",
1097 params->bssid[0], params->bssid[1], params->bssid[2],
1098 params->bssid[3], params->bssid[4], params->bssid[5]);
1099
1100 if (!wpa_cli_cmd_v("set_network %d bssid %s",
1101 resp.network_id, bssid_str)) {
1102 goto out;
1103 }
1104 }
1105
1106 /* enable and select network */
1107 if (!wpa_cli_cmd_v("enable_network %d", resp.network_id)) {
1108 goto out;
1109 }
1110
1111 if (!wpa_cli_cmd_v("select_network %d", resp.network_id)) {
1112 goto out;
1113 }
1114
1115 memset(&last_wifi_conn_params, 0, sizeof(struct wifi_connect_req_params));
1116 memcpy((void *)&last_wifi_conn_params, params, sizeof(struct wifi_connect_req_params));
1117 return 0;
1118
1119 rem_net:
1120 if (!wpa_cli_cmd_v("remove_network %d", resp.network_id)) {
1121 goto out;
1122 }
1123
1124 out:
1125 return ret;
1126 }
1127
wpas_disconnect_network(const struct device * dev,int cur_mode)1128 static int wpas_disconnect_network(const struct device *dev, int cur_mode)
1129 {
1130 struct net_if *iface = net_if_lookup_by_dev(dev);
1131 struct wpa_supplicant *wpa_s;
1132 bool is_ap = false;
1133 int ret = 0;
1134
1135 if (!iface) {
1136 ret = -ENOENT;
1137 wpa_printf(MSG_ERROR, "Interface for device %s not found", dev->name);
1138 return ret;
1139 }
1140
1141 wpa_s = get_wpa_s_handle(dev);
1142 if (!wpa_s) {
1143 ret = -1;
1144 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
1145 goto out;
1146 }
1147
1148 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1149
1150 if (wpa_s->current_ssid && wpa_s->current_ssid->mode != cur_mode) {
1151 ret = -EBUSY;
1152 wpa_printf(MSG_ERROR, "Interface %s is not in %s mode", dev->name,
1153 cur_mode == WPAS_MODE_INFRA ? "STA" : "AP");
1154 goto out;
1155 }
1156
1157 is_ap = (cur_mode == WPAS_MODE_AP);
1158
1159 wpas_api_ctrl.dev = dev;
1160 wpas_api_ctrl.requested_op = DISCONNECT;
1161
1162 if (!wpa_cli_cmd_v("disconnect")) {
1163 goto out;
1164 }
1165
1166 out:
1167 k_mutex_unlock(&wpa_supplicant_mutex);
1168
1169 if (ret) {
1170 wpa_printf(MSG_ERROR, "Disconnect failed: %s", strerror(-ret));
1171 return ret;
1172 }
1173
1174 wpa_supp_restart_status_work();
1175
1176 ret = wait_for_disconnect_complete(dev);
1177 #ifdef CONFIG_AP
1178 if (is_ap) {
1179 supplicant_send_wifi_mgmt_ap_status(wpa_s,
1180 NET_EVENT_WIFI_CMD_AP_DISABLE_RESULT,
1181 ret == 0 ? WIFI_STATUS_AP_SUCCESS : WIFI_STATUS_AP_FAIL);
1182 } else {
1183 #else
1184 {
1185 #endif /* CONFIG_AP */
1186 wifi_mgmt_raise_disconnect_complete_event(iface, ret);
1187 }
1188
1189 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
1190 wpas_remove_certs(wpa_s);
1191 #endif
1192
1193 if (!wpa_cli_cmd_v("remove_network all")) {
1194 wpa_printf(MSG_ERROR, "Failed to remove all networks");
1195 }
1196
1197 return ret;
1198 }
1199
1200 /* Public API */
1201 int supplicant_connect(const struct device *dev, struct wifi_connect_req_params *params)
1202 {
1203 struct wpa_supplicant *wpa_s;
1204 int ret = 0;
1205
1206 if (!net_if_is_admin_up(net_if_lookup_by_dev(dev))) {
1207 wpa_printf(MSG_ERROR,
1208 "Interface %s is down, dropping connect",
1209 dev->name);
1210 return -1;
1211 }
1212
1213 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1214
1215 wpa_s = get_wpa_s_handle(dev);
1216 if (!wpa_s) {
1217 ret = -1;
1218 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
1219 goto out;
1220 }
1221
1222 /* Allow connect in STA mode only even if we are connected already */
1223 if (wpa_s->current_ssid && wpa_s->current_ssid->mode != WPAS_MODE_INFRA) {
1224 ret = -EBUSY;
1225 wpa_printf(MSG_ERROR, "Interface %s is not in STA mode", dev->name);
1226 goto out;
1227 }
1228
1229 ret = wpas_add_and_config_network(wpa_s, params, false);
1230 if (ret) {
1231 wpa_printf(MSG_ERROR, "Failed to add and configure network for STA mode: %d", ret);
1232 goto out;
1233 }
1234
1235 wpas_api_ctrl.dev = dev;
1236 wpas_api_ctrl.requested_op = CONNECT;
1237 wpas_api_ctrl.connection_timeout = params->timeout;
1238
1239 out:
1240 k_mutex_unlock(&wpa_supplicant_mutex);
1241
1242 if (!ret) {
1243 wpa_supp_restart_status_work();
1244 }
1245
1246 return ret;
1247 }
1248
1249 int supplicant_disconnect(const struct device *dev)
1250 {
1251 return wpas_disconnect_network(dev, WPAS_MODE_INFRA);
1252 }
1253
1254 enum wifi_mfp_options get_mfp(enum mfp_options supp_mfp_option)
1255 {
1256 switch (supp_mfp_option) {
1257 case NO_MGMT_FRAME_PROTECTION:
1258 return WIFI_MFP_DISABLE;
1259 case MGMT_FRAME_PROTECTION_OPTIONAL:
1260 return WIFI_MFP_OPTIONAL;
1261 case MGMT_FRAME_PROTECTION_REQUIRED:
1262 return WIFI_MFP_REQUIRED;
1263 default:
1264 wpa_printf(MSG_ERROR, "Invalid mfp mapping %d", supp_mfp_option);
1265 break;
1266 }
1267
1268 return WIFI_MFP_DISABLE;
1269 }
1270
1271 static enum wifi_iface_mode get_iface_mode(enum wpas_mode supp_mode)
1272 {
1273 switch (supp_mode) {
1274 case WPAS_MODE_INFRA:
1275 return WIFI_MODE_INFRA;
1276 case WPAS_MODE_IBSS:
1277 return WIFI_MODE_IBSS;
1278 case WPAS_MODE_AP:
1279 return WIFI_MODE_AP;
1280 case WPAS_MODE_P2P_GO:
1281 return WIFI_MODE_P2P_GO;
1282 case WPAS_MODE_P2P_GROUP_FORMATION:
1283 return WIFI_MODE_P2P_GROUP_FORMATION;
1284 case WPAS_MODE_MESH:
1285 return WIFI_MODE_MESH;
1286 default:
1287 break;
1288 }
1289
1290 return WIFI_MODE_UNKNOWN;
1291 }
1292
1293 int supplicant_status(const struct device *dev, struct wifi_iface_status *status)
1294 {
1295 struct net_if *iface = net_if_lookup_by_dev(dev);
1296 struct wpa_supplicant *wpa_s;
1297 int ret = -1;
1298 struct wpa_signal_info *si = NULL;
1299 struct wpa_conn_info *conn_info = NULL;
1300
1301 if (!iface) {
1302 ret = -ENOENT;
1303 wpa_printf(MSG_ERROR, "Interface for device %s not found", dev->name);
1304 return ret;
1305 }
1306
1307 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1308
1309 wpa_s = get_wpa_s_handle(dev);
1310 if (!wpa_s) {
1311 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
1312 goto out;
1313 }
1314
1315 si = os_zalloc(sizeof(struct wpa_signal_info));
1316 if (!si) {
1317 wpa_printf(MSG_ERROR, "Failed to allocate memory for signal info");
1318 goto out;
1319 }
1320
1321 status->state = wpa_s->wpa_state; /* 1-1 Mapping */
1322
1323 if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
1324 struct wpa_ssid *ssid = wpa_s->current_ssid;
1325 u8 channel;
1326 struct signal_poll_resp signal_poll;
1327 u8 *_ssid;
1328 size_t ssid_len;
1329 struct status_resp cli_status;
1330 int proto;
1331 int key_mgmt;
1332 int sae_pwe;
1333
1334 if (!ssid) {
1335 wpa_printf(MSG_ERROR, "Failed to get current ssid");
1336 goto out;
1337 }
1338
1339 _ssid = ssid->ssid;
1340 ssid_len = ssid->ssid_len;
1341 proto = ssid->proto;
1342 key_mgmt = ssid->key_mgmt;
1343 sae_pwe = wpa_s->conf->sae_pwe;
1344 os_memcpy(status->bssid, wpa_s->bssid, WIFI_MAC_ADDR_LEN);
1345 status->band = wpas_band_to_zephyr(wpas_freq_to_band(wpa_s->assoc_freq));
1346 status->wpa3_ent_type = wpas_key_mgmt_to_zephyr_wpa3_ent(key_mgmt);
1347 status->security = wpas_key_mgmt_to_zephyr(0, ssid, key_mgmt, proto, sae_pwe);
1348 status->mfp = get_mfp(ssid->ieee80211w);
1349 ieee80211_freq_to_chan(wpa_s->assoc_freq, &channel);
1350 status->channel = channel;
1351
1352 if (ssid_len == 0) {
1353 int _res = z_wpa_ctrl_status(&cli_status);
1354
1355 if (_res < 0) {
1356 ssid_len = 0;
1357 } else {
1358 ssid_len = cli_status.ssid_len;
1359 }
1360
1361 _ssid = cli_status.ssid;
1362 }
1363
1364 os_memcpy(status->ssid, _ssid, ssid_len);
1365 status->ssid_len = ssid_len;
1366 status->iface_mode = get_iface_mode(ssid->mode);
1367
1368 if (wpa_s->connection_set == 1) {
1369 status->link_mode = wpa_s->connection_he ? WIFI_6 :
1370 wpa_s->connection_vht ? WIFI_5 :
1371 wpa_s->connection_ht ? WIFI_4 :
1372 wpa_s->connection_g ? WIFI_3 :
1373 wpa_s->connection_a ? WIFI_2 :
1374 wpa_s->connection_b ? WIFI_1 :
1375 WIFI_0;
1376 } else {
1377 status->link_mode = WIFI_LINK_MODE_UNKNOWN;
1378 }
1379
1380 status->rssi = -WPA_INVALID_NOISE;
1381 if (status->iface_mode == WIFI_MODE_INFRA) {
1382 ret = z_wpa_ctrl_signal_poll(&signal_poll);
1383 if (!ret) {
1384 status->rssi = signal_poll.rssi;
1385 status->current_phy_tx_rate = signal_poll.current_txrate;
1386 } else {
1387 wpa_printf(MSG_WARNING, "%s: Failed to read signal poll info",
1388 __func__);
1389 }
1390 }
1391
1392 conn_info = os_zalloc(sizeof(struct wpa_conn_info));
1393 if (!conn_info) {
1394 wpa_printf(MSG_ERROR, "%s:Failed to allocate memory\n",
1395 __func__);
1396 ret = -ENOMEM;
1397 goto out;
1398 }
1399
1400 ret = wpa_drv_get_conn_info(wpa_s, conn_info);
1401 if (!ret) {
1402 status->beacon_interval = conn_info->beacon_interval;
1403 status->dtim_period = conn_info->dtim_period;
1404 status->twt_capable = conn_info->twt_capable;
1405 } else {
1406 wpa_printf(MSG_WARNING, "%s: Failed to get connection info\n",
1407 __func__);
1408
1409 status->beacon_interval = 0;
1410 status->dtim_period = 0;
1411 status->twt_capable = false;
1412 ret = 0;
1413 }
1414
1415 os_free(conn_info);
1416 } else {
1417 ret = 0;
1418 }
1419
1420 out:
1421 os_free(si);
1422 k_mutex_unlock(&wpa_supplicant_mutex);
1423 return ret;
1424 }
1425
1426 /* Below APIs are not natively supported by WPA supplicant, so,
1427 * these are just wrappers around driver offload APIs. But it is
1428 * transparent to the user.
1429 *
1430 * In the future these might be implemented natively by the WPA
1431 * supplicant.
1432 */
1433
1434 const struct wifi_mgmt_ops *const get_wifi_mgmt_api(const struct device *dev)
1435 {
1436 struct net_wifi_mgmt_offload *api = (struct net_wifi_mgmt_offload *)dev->api;
1437
1438 return api ? api->wifi_mgmt_api : NULL;
1439 }
1440
1441 int supplicant_get_version(const struct device *dev, struct wifi_version *params)
1442 {
1443 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1444
1445 if (!wifi_mgmt_api || !wifi_mgmt_api->get_version) {
1446 wpa_printf(MSG_ERROR, "get_version not supported");
1447 return -ENOTSUP;
1448 }
1449
1450 return wifi_mgmt_api->get_version(dev, params);
1451 }
1452
1453 int supplicant_scan(const struct device *dev, struct wifi_scan_params *params,
1454 scan_result_cb_t cb)
1455 {
1456 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1457
1458 if (!wifi_mgmt_api || !wifi_mgmt_api->scan) {
1459 wpa_printf(MSG_ERROR, "Scan not supported");
1460 return -ENOTSUP;
1461 }
1462
1463 return wifi_mgmt_api->scan(dev, params, cb);
1464 }
1465
1466 #ifdef CONFIG_NET_STATISTICS_WIFI
1467 int supplicant_get_stats(const struct device *dev, struct net_stats_wifi *stats)
1468 {
1469 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1470
1471 if (!wifi_mgmt_api || !wifi_mgmt_api->get_stats) {
1472 wpa_printf(MSG_ERROR, "Get stats not supported");
1473 return -ENOTSUP;
1474 }
1475
1476 return wifi_mgmt_api->get_stats(dev, stats);
1477 }
1478
1479 int supplicant_reset_stats(const struct device *dev)
1480 {
1481 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1482
1483 if (!wifi_mgmt_api || !wifi_mgmt_api->reset_stats) {
1484 wpa_printf(MSG_WARNING, "Reset stats not supported");
1485 return -ENOTSUP;
1486 }
1487
1488 return wifi_mgmt_api->reset_stats(dev);
1489 }
1490 #endif /* CONFIG_NET_STATISTICS_WIFI */
1491
1492 int supplicant_pmksa_flush(const struct device *dev)
1493 {
1494 struct wpa_supplicant *wpa_s;
1495 int ret = 0;
1496
1497 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1498
1499 wpa_s = get_wpa_s_handle(dev);
1500 if (!wpa_s) {
1501 ret = -1;
1502 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
1503 goto out;
1504 }
1505
1506 if (!wpa_cli_cmd_v("pmksa_flush")) {
1507 ret = -1;
1508 wpa_printf(MSG_ERROR, "pmksa_flush failed");
1509 goto out;
1510 }
1511
1512 out:
1513 k_mutex_unlock(&wpa_supplicant_mutex);
1514 return ret;
1515 }
1516
1517 int supplicant_11k_cfg(const struct device *dev, struct wifi_11k_params *params)
1518 {
1519 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1520
1521 if (!wifi_mgmt_api || !wifi_mgmt_api->cfg_11k) {
1522 wpa_printf(MSG_ERROR, "cfg 11k not supported");
1523 return -ENOTSUP;
1524 }
1525
1526 return wifi_mgmt_api->cfg_11k(dev, params);
1527 }
1528
1529 int supplicant_11k_neighbor_request(const struct device *dev, struct wifi_11k_params *params)
1530 {
1531 struct wpa_supplicant *wpa_s;
1532 int ssid_len;
1533
1534 wpa_s = get_wpa_s_handle(dev);
1535 if (!wpa_s) {
1536 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
1537 return -1;
1538 }
1539
1540 if (wpa_s->reassociate || (wpa_s->wpa_state >= WPA_AUTHENTICATING &&
1541 wpa_s->wpa_state < WPA_COMPLETED)) {
1542 wpa_printf(MSG_INFO, "Reassociation is in progress, skip");
1543 return 0;
1544 }
1545
1546 if (params) {
1547 ssid_len = strlen(params->ssid);
1548 } else {
1549 ssid_len = 0;
1550 }
1551
1552 if (ssid_len > 0) {
1553 if (ssid_len > WIFI_SSID_MAX_LEN) {
1554 wpa_printf(MSG_ERROR, "%s: ssid too long %u",
1555 __func__, ssid_len);
1556 return -1;
1557 }
1558
1559 if (!wpa_cli_cmd_v("neighbor_rep_request ssid %s",
1560 params->ssid)) {
1561 wpa_printf(MSG_ERROR,
1562 "%s: cli cmd <neighbor_rep_request ssid %s> fail",
1563 __func__, params->ssid);
1564 return -1;
1565 }
1566 } else {
1567 if (!wpa_cli_cmd_v("neighbor_rep_request")) {
1568 wpa_printf(MSG_ERROR,
1569 "%s: cli cmd <neighbor_rep_request> fail",
1570 __func__);
1571 return -1;
1572 }
1573 }
1574
1575 return 0;
1576 }
1577
1578 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_ROAMING
1579 #define SUPPLICANT_CANDIDATE_SCAN_CMD_BUF_SIZE 100
1580 int supplicant_candidate_scan(const struct device *dev, struct wifi_scan_params *params)
1581 {
1582 int i = 0;
1583 char cmd[SUPPLICANT_CANDIDATE_SCAN_CMD_BUF_SIZE] = {0};
1584 char *pos = cmd;
1585 char *end = pos + SUPPLICANT_CANDIDATE_SCAN_CMD_BUF_SIZE;
1586 int freq = 0;
1587
1588 strcpy(pos, "freq=");
1589 pos += 5;
1590 while (params->band_chan[i].channel) {
1591 if (i > 0) {
1592 pos += snprintf(pos, end - pos, ",");
1593 }
1594 freq = chan_to_freq(params->band_chan[i].channel);
1595 pos += snprintf(pos, end - pos, "%d", freq);
1596 i++;
1597 }
1598
1599 if (!wpa_cli_cmd_v("scan %s", cmd)) {
1600 wpa_printf(MSG_ERROR,
1601 "%s: cli cmd <scan %s> fail",
1602 __func__, cmd);
1603 return -1;
1604 }
1605
1606 return 0;
1607 }
1608
1609 int supplicant_11r_roaming(const struct device *dev)
1610 {
1611 struct wpa_supplicant *wpa_s;
1612 int ret = 0;
1613
1614 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1615
1616 wpa_s = get_wpa_s_handle(dev);
1617 if (!wpa_s) {
1618 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
1619 ret = -1;
1620 goto out;
1621 }
1622
1623 if (wpa_s->reassociate || (wpa_s->wpa_state >= WPA_AUTHENTICATING &&
1624 wpa_s->wpa_state < WPA_COMPLETED)) {
1625 wpa_printf(MSG_INFO, "Reassociation is in progress, skip");
1626 ret = 0;
1627 goto out;
1628 }
1629
1630 if (!wpa_cli_cmd_v("reassociate")) {
1631 wpa_printf(MSG_ERROR, "%s: cli cmd <reassociate> fail",
1632 __func__);
1633 ret = -1;
1634 goto out;
1635 }
1636
1637 out:
1638 k_mutex_unlock(&wpa_supplicant_mutex);
1639 return ret;
1640 }
1641 #endif
1642
1643 int supplicant_set_power_save(const struct device *dev, struct wifi_ps_params *params)
1644 {
1645 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1646
1647 if (!wifi_mgmt_api || !wifi_mgmt_api->set_power_save) {
1648 wpa_printf(MSG_ERROR, "Set power save not supported");
1649 return -ENOTSUP;
1650 }
1651
1652 return wifi_mgmt_api->set_power_save(dev, params);
1653 }
1654
1655 int supplicant_set_twt(const struct device *dev, struct wifi_twt_params *params)
1656 {
1657 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1658
1659 if (!wifi_mgmt_api || !wifi_mgmt_api->set_twt) {
1660 wpa_printf(MSG_ERROR, "Set TWT not supported");
1661 return -ENOTSUP;
1662 }
1663
1664 return wifi_mgmt_api->set_twt(dev, params);
1665 }
1666
1667 int supplicant_set_btwt(const struct device *dev, struct wifi_twt_params *params)
1668 {
1669 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1670
1671 if (!wifi_mgmt_api || !wifi_mgmt_api->set_btwt) {
1672 wpa_printf(MSG_ERROR, "Set Broadcast TWT not supported");
1673 return -ENOTSUP;
1674 }
1675
1676 return wifi_mgmt_api->set_btwt(dev, params);
1677 }
1678
1679 int supplicant_get_power_save_config(const struct device *dev,
1680 struct wifi_ps_config *config)
1681 {
1682 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1683
1684 if (!wifi_mgmt_api || !wifi_mgmt_api->get_power_save_config) {
1685 wpa_printf(MSG_ERROR, "Get power save config not supported");
1686 return -ENOTSUP;
1687 }
1688
1689 return wifi_mgmt_api->get_power_save_config(dev, config);
1690 }
1691
1692 int supplicant_reg_domain(const struct device *dev,
1693 struct wifi_reg_domain *reg_domain)
1694 {
1695 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1696 struct wpa_supplicant *wpa_s;
1697 int ret = -1;
1698
1699 if (!wifi_mgmt_api || !wifi_mgmt_api->reg_domain) {
1700 wpa_printf(MSG_ERROR, "Regulatory domain not supported");
1701 return -ENOTSUP;
1702 }
1703
1704 if (reg_domain->oper == WIFI_MGMT_GET) {
1705 return wifi_mgmt_api->reg_domain(dev, reg_domain);
1706 }
1707
1708 if (reg_domain->oper == WIFI_MGMT_SET) {
1709 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1710
1711 wpa_s = get_wpa_s_handle(dev);
1712 if (!wpa_s) {
1713 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
1714 goto out;
1715 }
1716
1717 if (!wpa_cli_cmd_v("set country %s", reg_domain->country_code)) {
1718 goto out;
1719 }
1720
1721 if (IS_ENABLED(CONFIG_WIFI_NM_HOSTAPD_AP)) {
1722 if (!hostapd_ap_reg_domain(reg_domain)) {
1723 goto out;
1724 }
1725 }
1726
1727 ret = 0;
1728
1729 out:
1730 k_mutex_unlock(&wpa_supplicant_mutex);
1731 }
1732
1733 return ret;
1734 }
1735
1736 int supplicant_mode(const struct device *dev, struct wifi_mode_info *mode)
1737 {
1738 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1739
1740 if (!wifi_mgmt_api || !wifi_mgmt_api->mode) {
1741 wpa_printf(MSG_ERROR, "Setting mode not supported");
1742 return -ENOTSUP;
1743 }
1744
1745 return wifi_mgmt_api->mode(dev, mode);
1746 }
1747
1748 int supplicant_filter(const struct device *dev, struct wifi_filter_info *filter)
1749 {
1750 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1751
1752 if (!wifi_mgmt_api || !wifi_mgmt_api->filter) {
1753 wpa_printf(MSG_ERROR, "Setting filter not supported");
1754 return -ENOTSUP;
1755 }
1756
1757 return wifi_mgmt_api->filter(dev, filter);
1758 }
1759
1760 int supplicant_channel(const struct device *dev, struct wifi_channel_info *channel)
1761 {
1762 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1763
1764 if (!wifi_mgmt_api || !wifi_mgmt_api->channel) {
1765 wpa_printf(MSG_ERROR, "Setting channel not supported");
1766 return -ENOTSUP;
1767 }
1768
1769 return wifi_mgmt_api->channel(dev, channel);
1770 }
1771
1772 int supplicant_set_rts_threshold(const struct device *dev, unsigned int rts_threshold)
1773 {
1774 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1775
1776 if (!wifi_mgmt_api || !wifi_mgmt_api->set_rts_threshold) {
1777 wpa_printf(MSG_ERROR, "Set RTS not supported");
1778 return -ENOTSUP;
1779 }
1780
1781 return wifi_mgmt_api->set_rts_threshold(dev, rts_threshold);
1782 }
1783
1784 int supplicant_get_rts_threshold(const struct device *dev, unsigned int *rts_threshold)
1785 {
1786 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1787
1788 if (!wifi_mgmt_api || !wifi_mgmt_api->get_rts_threshold) {
1789 wpa_printf(MSG_ERROR, "Get RTS not supported");
1790 return -ENOTSUP;
1791 }
1792
1793 return wifi_mgmt_api->get_rts_threshold(dev, rts_threshold);
1794 }
1795
1796 bool supplicant_bss_support_neighbor_rep(const struct device *dev)
1797 {
1798 struct wpa_supplicant *wpa_s;
1799 bool is_support = false;
1800 const u8 *rrm_ie = NULL;
1801
1802 wpa_s = get_wpa_s_handle(dev);
1803 if (!wpa_s) {
1804 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
1805 return false;
1806 }
1807
1808 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1809 if (!wpa_s->rrm.rrm_used) {
1810 goto out;
1811 }
1812
1813 rrm_ie = wpa_bss_get_ie(wpa_s->current_bss,
1814 WLAN_EID_RRM_ENABLED_CAPABILITIES);
1815 if (!rrm_ie || !(wpa_s->current_bss->caps & IEEE80211_CAP_RRM) ||
1816 !(rrm_ie[2] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
1817 goto out;
1818 }
1819 is_support = true;
1820 out:
1821 k_mutex_unlock(&wpa_supplicant_mutex);
1822 return is_support;
1823 }
1824
1825 int supplicant_bss_ext_capab(const struct device *dev, int capab)
1826 {
1827 struct wpa_supplicant *wpa_s;
1828 int is_support = 0;
1829
1830 wpa_s = get_wpa_s_handle(dev);
1831 if (!wpa_s) {
1832 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
1833 return 0;
1834 }
1835
1836 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1837 is_support = wpa_bss_ext_capab(wpa_s->current_bss, capab);
1838 k_mutex_unlock(&wpa_supplicant_mutex);
1839
1840 return is_support;
1841 }
1842
1843 int supplicant_legacy_roam(const struct device *dev)
1844 {
1845 struct wpa_supplicant *wpa_s;
1846 int ret = -1;
1847
1848 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1849
1850 wpa_s = get_wpa_s_handle(dev);
1851 if (!wpa_s) {
1852 ret = -1;
1853 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
1854 goto out;
1855 }
1856
1857 if (wpa_s->reassociate || (wpa_s->wpa_state >= WPA_AUTHENTICATING &&
1858 wpa_s->wpa_state < WPA_COMPLETED)) {
1859 wpa_printf(MSG_INFO, "Reassociation is in progress, skip");
1860 ret = 0;
1861 goto out;
1862 }
1863
1864 if (!wpa_cli_cmd_v("scan")) {
1865 goto out;
1866 }
1867
1868 ret = 0;
1869
1870 out:
1871 k_mutex_unlock(&wpa_supplicant_mutex);
1872
1873 return ret;
1874 }
1875
1876 int supplicant_set_bss_max_idle_period(const struct device *dev,
1877 unsigned short bss_max_idle_period)
1878 {
1879 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1880
1881 if (!wifi_mgmt_api || !wifi_mgmt_api->set_bss_max_idle_period) {
1882 wpa_printf(MSG_ERROR, "set_bss_max_idle_period is not supported");
1883 return -ENOTSUP;
1884 }
1885
1886 return wifi_mgmt_api->set_bss_max_idle_period(dev, bss_max_idle_period);
1887 }
1888
1889 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_WNM
1890 int supplicant_btm_query(const struct device *dev, uint8_t reason)
1891 {
1892 struct wpa_supplicant *wpa_s;
1893 int ret = -1;
1894
1895 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1896
1897 wpa_s = get_wpa_s_handle(dev);
1898 if (!wpa_s) {
1899 ret = -1;
1900 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
1901 goto out;
1902 }
1903
1904 if (wpa_s->reassociate || (wpa_s->wpa_state >= WPA_AUTHENTICATING &&
1905 wpa_s->wpa_state < WPA_COMPLETED)) {
1906 wpa_printf(MSG_INFO, "Reassociation is in progress, skip");
1907 ret = 0;
1908 goto out;
1909 }
1910
1911 if (!wpa_cli_cmd_v("wnm_bss_query %d", reason)) {
1912 goto out;
1913 }
1914
1915 ret = 0;
1916
1917 out:
1918 k_mutex_unlock(&wpa_supplicant_mutex);
1919
1920 return ret;
1921 }
1922 #endif
1923
1924 int supplicant_get_wifi_conn_params(const struct device *dev,
1925 struct wifi_connect_req_params *params)
1926 {
1927 struct wpa_supplicant *wpa_s;
1928 int ret = 0;
1929
1930 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1931
1932 wpa_s = get_wpa_s_handle(dev);
1933 if (!wpa_s) {
1934 ret = -1;
1935 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
1936 goto out;
1937 }
1938
1939 memcpy(params, &last_wifi_conn_params, sizeof(struct wifi_connect_req_params));
1940 out:
1941 k_mutex_unlock(&wpa_supplicant_mutex);
1942 return ret;
1943 }
1944
1945 static int supplicant_wps_pbc(const struct device *dev)
1946 {
1947 struct wpa_supplicant *wpa_s;
1948 int ret = -1;
1949
1950 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1951
1952 wpa_s = get_wpa_s_handle(dev);
1953 if (!wpa_s) {
1954 ret = -1;
1955 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
1956 goto out;
1957 }
1958
1959 if (!wpa_cli_cmd_v("wps_pbc")) {
1960 goto out;
1961 }
1962
1963 wpas_api_ctrl.dev = dev;
1964 wpas_api_ctrl.requested_op = WPS_PBC;
1965
1966 ret = 0;
1967
1968 out:
1969 k_mutex_unlock(&wpa_supplicant_mutex);
1970
1971 return ret;
1972 }
1973
1974 static int supplicant_wps_pin(const struct device *dev, struct wifi_wps_config_params *params)
1975 {
1976 struct wpa_supplicant *wpa_s;
1977 char *get_pin_cmd = "WPS_PIN get";
1978 int ret = -1;
1979
1980 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1981
1982 wpa_s = get_wpa_s_handle(dev);
1983 if (!wpa_s) {
1984 ret = -1;
1985 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
1986 goto out;
1987 }
1988
1989 if (params->oper == WIFI_WPS_PIN_GET) {
1990 if (zephyr_wpa_cli_cmd_resp(get_pin_cmd, params->pin)) {
1991 goto out;
1992 }
1993 } else if (params->oper == WIFI_WPS_PIN_SET) {
1994 if (!wpa_cli_cmd_v("wps_check_pin %s", params->pin)) {
1995 goto out;
1996 }
1997
1998 if (!wpa_cli_cmd_v("wps_pin any %s", params->pin)) {
1999 goto out;
2000 }
2001
2002 wpas_api_ctrl.dev = dev;
2003 wpas_api_ctrl.requested_op = WPS_PIN;
2004 } else {
2005 wpa_printf(MSG_ERROR, "Error wps pin operation : %d", params->oper);
2006 goto out;
2007 }
2008
2009 ret = 0;
2010
2011 out:
2012 k_mutex_unlock(&wpa_supplicant_mutex);
2013
2014 return ret;
2015 }
2016
2017 int supplicant_wps_config(const struct device *dev, struct wifi_wps_config_params *params)
2018 {
2019 int ret = 0;
2020
2021 if (params->oper == WIFI_WPS_PBC) {
2022 ret = supplicant_wps_pbc(dev);
2023 } else if (params->oper == WIFI_WPS_PIN_GET || params->oper == WIFI_WPS_PIN_SET) {
2024 ret = supplicant_wps_pin(dev, params);
2025 }
2026
2027 return ret;
2028 }
2029
2030 #ifdef CONFIG_AP
2031 int set_ap_bandwidth(const struct device *dev, enum wifi_frequency_bandwidths bandwidth)
2032 {
2033 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
2034 struct wifi_ap_config_params params = {0};
2035
2036 if (wifi_mgmt_api == NULL || wifi_mgmt_api->ap_config_params == NULL) {
2037 return -ENOTSUP;
2038 }
2039
2040 params.bandwidth = bandwidth;
2041 params.type = WIFI_AP_CONFIG_PARAM_BANDWIDTH;
2042 return wifi_mgmt_api->ap_config_params(dev, ¶ms);
2043 }
2044
2045 int supplicant_ap_enable(const struct device *dev,
2046 struct wifi_connect_req_params *params)
2047 {
2048 struct wpa_supplicant *wpa_s;
2049 int ret;
2050
2051 if (!net_if_is_admin_up(net_if_lookup_by_dev(dev))) {
2052 wpa_printf(MSG_ERROR,
2053 "Interface %s is down, dropping connect",
2054 dev->name);
2055 return -1;
2056 }
2057
2058 ret = set_ap_bandwidth(dev, params->bandwidth);
2059 if (ret && (ret != -ENOTSUP)) {
2060 wpa_printf(MSG_ERROR, "Failed to set ap bandwidth");
2061 return -EINVAL;
2062 }
2063
2064 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2065
2066 wpa_s = get_wpa_s_handle(dev);
2067 if (!wpa_s) {
2068 ret = -1;
2069 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2070 goto out;
2071 }
2072
2073 if (wpa_s->wpa_state != WPA_DISCONNECTED) {
2074 ret = -EBUSY;
2075 wpa_printf(MSG_ERROR, "Interface %s is not in disconnected state", dev->name);
2076 goto out;
2077 }
2078
2079 /* No need to check for existing network to join for SoftAP */
2080 wpa_s->conf->ap_scan = 2;
2081 /* Set BSS parameter max_num_sta to default configured value */
2082 wpa_s->conf->max_num_sta = CONFIG_WIFI_MGMT_AP_MAX_NUM_STA;
2083
2084 ret = wpas_add_and_config_network(wpa_s, params, true);
2085 if (ret) {
2086 wpa_printf(MSG_ERROR, "Failed to add and configure network for AP mode: %d", ret);
2087 goto out;
2088 }
2089
2090 out:
2091 k_mutex_unlock(&wpa_supplicant_mutex);
2092
2093 return ret;
2094 }
2095
2096 int supplicant_ap_disable(const struct device *dev)
2097 {
2098 struct wpa_supplicant *wpa_s;
2099 int ret = -1;
2100
2101 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2102
2103 wpa_s = get_wpa_s_handle(dev);
2104 if (!wpa_s) {
2105 ret = -1;
2106 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2107 goto out;
2108 }
2109
2110 ret = wpas_disconnect_network(dev, WPAS_MODE_AP);
2111 if (ret) {
2112 wpa_printf(MSG_ERROR, "Failed to disconnect from network");
2113 goto out;
2114 }
2115
2116 /* Restore ap_scan to default value */
2117 wpa_s->conf->ap_scan = 1;
2118
2119 out:
2120 k_mutex_unlock(&wpa_supplicant_mutex);
2121 return ret;
2122 }
2123
2124 int supplicant_ap_sta_disconnect(const struct device *dev,
2125 const uint8_t *mac_addr)
2126 {
2127 struct wpa_supplicant *wpa_s;
2128 int ret = -1;
2129
2130 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2131
2132 wpa_s = get_wpa_s_handle(dev);
2133 if (!wpa_s) {
2134 ret = -1;
2135 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2136 goto out;
2137 }
2138
2139 if (!mac_addr) {
2140 ret = -EINVAL;
2141 wpa_printf(MSG_ERROR, "Invalid MAC address");
2142 goto out;
2143 }
2144
2145 if (!wpa_cli_cmd_v("disassociate %02x:%02x:%02x:%02x:%02x:%02x",
2146 mac_addr[0], mac_addr[1], mac_addr[2],
2147 mac_addr[3], mac_addr[4], mac_addr[5])) {
2148 goto out;
2149 }
2150
2151 ret = 0;
2152
2153 out:
2154 k_mutex_unlock(&wpa_supplicant_mutex);
2155
2156 return ret;
2157 }
2158 #endif /* CONFIG_AP */
2159
2160 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP
2161 static const char *dpp_params_to_args_curve(int curve)
2162 {
2163 switch (curve) {
2164 case WIFI_DPP_CURVES_P_256:
2165 return "P-256";
2166 case WIFI_DPP_CURVES_P_384:
2167 return "P-384";
2168 case WIFI_DPP_CURVES_P_512:
2169 return "P-521";
2170 case WIFI_DPP_CURVES_BP_256:
2171 return "BP-256";
2172 case WIFI_DPP_CURVES_BP_384:
2173 return "BP-384";
2174 case WIFI_DPP_CURVES_BP_512:
2175 return "BP-512";
2176 default:
2177 return "P-256";
2178 }
2179 }
2180
2181 static const char *dpp_params_to_args_conf(int conf)
2182 {
2183 switch (conf) {
2184 case WIFI_DPP_CONF_STA:
2185 return "sta-dpp";
2186 case WIFI_DPP_CONF_AP:
2187 return "ap-dpp";
2188 case WIFI_DPP_CONF_QUERY:
2189 return "query";
2190 default:
2191 return "sta-dpp";
2192 }
2193 }
2194
2195 static const char *dpp_params_to_args_role(int role)
2196 {
2197 switch (role) {
2198 case WIFI_DPP_ROLE_CONFIGURATOR:
2199 return "configurator";
2200 case WIFI_DPP_ROLE_ENROLLEE:
2201 return "enrollee";
2202 case WIFI_DPP_ROLE_EITHER:
2203 return "either";
2204 default:
2205 return "either";
2206 }
2207 }
2208
2209 static void dpp_ssid_bin2str(char *dst, uint8_t *src, int max_len)
2210 {
2211 uint8_t *end = src + strlen(src);
2212
2213 /* do 4 bytes convert first */
2214 for (; (src + 4) < end; src += 4) {
2215 snprintf(dst, max_len, "%02x%02x%02x%02x",
2216 src[0], src[1], src[2], src[3]);
2217 dst += 8;
2218 }
2219
2220 /* then do 1 byte convert */
2221 for (; src < end; src++) {
2222 snprintf(dst, max_len, "%02x", src[0]);
2223 dst += 2;
2224 }
2225 }
2226
2227 #define STR_CUR_TO_END(cur) (cur) = (&(cur)[0] + strlen((cur)))
2228
2229 int dpp_params_to_cmd(struct wifi_dpp_params *params, char *cmd, size_t max_len)
2230 {
2231 char *pos = cmd;
2232 char *end = cmd + max_len;
2233
2234 switch (params->action) {
2235 case WIFI_DPP_CONFIGURATOR_ADD:
2236 strncpy(pos, "DPP_CONFIGURATOR_ADD", end - pos);
2237 STR_CUR_TO_END(pos);
2238
2239 if (params->configurator_add.curve) {
2240 snprintf(pos, end - pos, " curve=%s",
2241 dpp_params_to_args_curve(params->configurator_add.curve));
2242 STR_CUR_TO_END(pos);
2243 }
2244
2245 if (params->configurator_add.net_access_key_curve) {
2246 snprintf(pos, end - pos, " net_access_key_curve=%s",
2247 dpp_params_to_args_curve(
2248 params->configurator_add.net_access_key_curve));
2249 }
2250 break;
2251 case WIFI_DPP_AUTH_INIT:
2252 strncpy(pos, "DPP_AUTH_INIT", end - pos);
2253 STR_CUR_TO_END(pos);
2254
2255 if (params->auth_init.peer) {
2256 snprintf(pos, end - pos, " peer=%d", params->auth_init.peer);
2257 STR_CUR_TO_END(pos);
2258 }
2259
2260 if (params->auth_init.conf) {
2261 snprintf(pos, end - pos, " conf=%s",
2262 dpp_params_to_args_conf(
2263 params->auth_init.conf));
2264 STR_CUR_TO_END(pos);
2265 }
2266
2267 if (params->auth_init.ssid[0]) {
2268 strncpy(pos, " ssid=", end - pos);
2269 STR_CUR_TO_END(pos);
2270 dpp_ssid_bin2str(pos, params->auth_init.ssid,
2271 WIFI_SSID_MAX_LEN * 2);
2272 STR_CUR_TO_END(pos);
2273 }
2274
2275 if (params->auth_init.configurator) {
2276 snprintf(pos, end - pos, " configurator=%d",
2277 params->auth_init.configurator);
2278 STR_CUR_TO_END(pos);
2279 }
2280
2281 if (params->auth_init.role) {
2282 snprintf(pos, end - pos, " role=%s",
2283 dpp_params_to_args_role(
2284 params->auth_init.role));
2285 }
2286 break;
2287 case WIFI_DPP_QR_CODE:
2288 strncpy(pos, "DPP_QR_CODE", end - pos);
2289 STR_CUR_TO_END(pos);
2290
2291 if (params->dpp_qr_code[0]) {
2292 snprintf(pos, end - pos, " %s", params->dpp_qr_code);
2293 }
2294 break;
2295 case WIFI_DPP_CHIRP:
2296 strncpy(pos, "DPP_CHIRP", end - pos);
2297 STR_CUR_TO_END(pos);
2298
2299 if (params->chirp.id) {
2300 snprintf(pos, end - pos, " own=%d", params->chirp.id);
2301 STR_CUR_TO_END(pos);
2302 }
2303
2304 if (params->chirp.freq) {
2305 snprintf(pos, end - pos, " listen=%d", params->chirp.freq);
2306 }
2307 break;
2308 case WIFI_DPP_LISTEN:
2309 strncpy(pos, "DPP_LISTEN", end - pos);
2310 STR_CUR_TO_END(pos);
2311
2312 if (params->listen.freq) {
2313 snprintf(pos, end - pos, " %d", params->listen.freq);
2314 STR_CUR_TO_END(pos);
2315 }
2316
2317 if (params->listen.role) {
2318 snprintf(pos, end - pos, " role=%s",
2319 dpp_params_to_args_role(
2320 params->listen.role));
2321 }
2322 break;
2323 case WIFI_DPP_BOOTSTRAP_GEN:
2324 strncpy(pos, "DPP_BOOTSTRAP_GEN", end - pos);
2325 STR_CUR_TO_END(pos);
2326
2327 if (params->bootstrap_gen.type) {
2328 strncpy(pos, " type=qrcode", end - pos);
2329 STR_CUR_TO_END(pos);
2330 }
2331
2332 if (params->bootstrap_gen.op_class &&
2333 params->bootstrap_gen.chan) {
2334 snprintf(pos, end - pos, " chan=%d/%d",
2335 params->bootstrap_gen.op_class,
2336 params->bootstrap_gen.chan);
2337 STR_CUR_TO_END(pos);
2338 }
2339
2340 /* mac is mandatory, even if it is zero mac address */
2341 snprintf(pos, end - pos, " mac=%02x:%02x:%02x:%02x:%02x:%02x",
2342 params->bootstrap_gen.mac[0], params->bootstrap_gen.mac[1],
2343 params->bootstrap_gen.mac[2], params->bootstrap_gen.mac[3],
2344 params->bootstrap_gen.mac[4], params->bootstrap_gen.mac[5]);
2345 STR_CUR_TO_END(pos);
2346
2347 if (params->bootstrap_gen.curve) {
2348 snprintf(pos, end - pos, " curve=%s",
2349 dpp_params_to_args_curve(params->bootstrap_gen.curve));
2350 }
2351 break;
2352 case WIFI_DPP_BOOTSTRAP_GET_URI:
2353 snprintf(pos, end - pos, "DPP_BOOTSTRAP_GET_URI %d", params->id);
2354 break;
2355 case WIFI_DPP_SET_CONF_PARAM:
2356 strncpy(pos, "SET dpp_configurator_params", end - pos);
2357 STR_CUR_TO_END(pos);
2358
2359 if (params->configurator_set.peer) {
2360 snprintf(pos, end - pos, " peer=%d", params->configurator_set.peer);
2361 STR_CUR_TO_END(pos);
2362 }
2363
2364 if (params->configurator_set.conf) {
2365 snprintf(pos, end - pos, " conf=%s",
2366 dpp_params_to_args_conf(
2367 params->configurator_set.conf));
2368 STR_CUR_TO_END(pos);
2369 }
2370
2371 if (params->configurator_set.ssid[0]) {
2372 strncpy(pos, " ssid=", end - pos);
2373 STR_CUR_TO_END(pos);
2374 dpp_ssid_bin2str(pos, params->configurator_set.ssid,
2375 WIFI_SSID_MAX_LEN * 2);
2376 STR_CUR_TO_END(pos);
2377 }
2378
2379 if (params->configurator_set.configurator) {
2380 snprintf(pos, end - pos, " configurator=%d",
2381 params->configurator_set.configurator);
2382 STR_CUR_TO_END(pos);
2383 }
2384
2385 if (params->configurator_set.role) {
2386 snprintf(pos, end - pos, " role=%s",
2387 dpp_params_to_args_role(
2388 params->configurator_set.role));
2389 STR_CUR_TO_END(pos);
2390 }
2391
2392 if (params->configurator_set.curve) {
2393 snprintf(pos, end - pos, " curve=%s",
2394 dpp_params_to_args_curve(params->configurator_set.curve));
2395 STR_CUR_TO_END(pos);
2396 }
2397
2398 if (params->configurator_set.net_access_key_curve) {
2399 snprintf(pos, end - pos, " net_access_key_curve=%s",
2400 dpp_params_to_args_curve(
2401 params->configurator_set.net_access_key_curve));
2402 }
2403 break;
2404 case WIFI_DPP_SET_WAIT_RESP_TIME:
2405 snprintf(pos, end - pos, "SET dpp_resp_wait_time %d",
2406 params->dpp_resp_wait_time);
2407 break;
2408 case WIFI_DPP_RECONFIG:
2409 snprintf(pos, end - pos, "DPP_RECONFIG %d", params->network_id);
2410 break;
2411 default:
2412 wpa_printf(MSG_ERROR, "Unknown DPP action");
2413 return -EINVAL;
2414 }
2415
2416 return 0;
2417 }
2418
2419 int supplicant_dpp_dispatch(const struct device *dev, struct wifi_dpp_params *params)
2420 {
2421 int ret;
2422 char *cmd = NULL;
2423
2424 if (params == NULL) {
2425 return -EINVAL;
2426 }
2427
2428 cmd = os_zalloc(SUPPLICANT_DPP_CMD_BUF_SIZE);
2429 if (cmd == NULL) {
2430 return -ENOMEM;
2431 }
2432
2433 /* leave one byte always be 0 */
2434 ret = dpp_params_to_cmd(params, cmd, SUPPLICANT_DPP_CMD_BUF_SIZE - 2);
2435 if (ret) {
2436 os_free(cmd);
2437 return ret;
2438 }
2439
2440 wpa_printf(MSG_DEBUG, "wpa_cli %s", cmd);
2441 if (zephyr_wpa_cli_cmd_resp(cmd, params->resp)) {
2442 os_free(cmd);
2443 return -ENOEXEC;
2444 }
2445
2446 os_free(cmd);
2447 return 0;
2448 }
2449 #endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP */
2450
2451 int supplicant_config_params(const struct device *dev, struct wifi_config_params *params)
2452 {
2453 struct wpa_supplicant *wpa_s;
2454 int ret = 0;
2455
2456 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2457
2458 wpa_s = get_wpa_s_handle(dev);
2459 if (!wpa_s) {
2460 ret = -ENOENT;
2461 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
2462 goto out;
2463 }
2464
2465 if (params->type & WIFI_CONFIG_PARAM_OKC) {
2466 if (!wpa_cli_cmd_v("set okc %d", params->okc)) {
2467 ret = -EINVAL;
2468 wpa_printf(MSG_ERROR, "Failed to set OKC");
2469 goto out;
2470 }
2471 wpa_printf(MSG_DEBUG, "Set OKC: %d", params->okc);
2472 }
2473
2474 out:
2475 k_mutex_unlock(&wpa_supplicant_mutex);
2476 return ret;
2477 }
2478