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