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