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, &params);
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