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