1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef WIFI_CREDENTIALS_H__
8 #define WIFI_CREDENTIALS_H__
9 
10 #include <zephyr/types.h>
11 #include <zephyr/net/wifi.h>
12 #include <zephyr/kernel.h>
13 
14 /**
15  * @defgroup wifi_credentials Wi-Fi credentials library
16  * @ingroup networking
17  * @since 4.0
18  * @version 0.1.0
19  * @{
20  * @brief Library that provides a way to store and load Wi-Fi credentials.
21  */
22 
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26 
27 /* this entry contains a BSSID */
28 #define WIFI_CREDENTIALS_FLAG_BSSID        BIT(0)
29 /* this entry is to be preferred over others */
30 #define WIFI_CREDENTIALS_FLAG_FAVORITE     BIT(1)
31 /* this entry can use the 2.4 GHz band */
32 #define WIFI_CREDENTIALS_FLAG_2_4GHz       BIT(2)
33 /* this entry can use the 5 GHz band */
34 #define WIFI_CREDENTIALS_FLAG_5GHz         BIT(3)
35 /* this entry requires management frame protection */
36 #define WIFI_CREDENTIALS_FLAG_MFP_REQUIRED BIT(4)
37 /* this entry disables management frame protection */
38 #define WIFI_CREDENTIALS_FLAG_MFP_DISABLED BIT(5)
39 
40 #define WIFI_CREDENTIALS_MAX_PASSWORD_LEN                                                          \
41 	MAX(WIFI_PSK_MAX_LEN, CONFIG_WIFI_CREDENTIALS_SAE_PASSWORD_LENGTH)
42 
43 /**
44  * @brief Wi-Fi credentials entry header
45  * @note Every settings entry starts with this header.
46  *       Depending on the `type` field, the header can be casted to a larger type.
47  *       In addition to SSID (usually a string) and BSSID (a MAC address),
48  *       a `flags` field can be used to control some detail settings.
49  *
50  */
51 struct wifi_credentials_header {
52 	enum wifi_security_type type;     /**< Wi-Fi security type */
53 	char ssid[WIFI_SSID_MAX_LEN];     /**< SSID (Service Set Identifier) */
54 	size_t ssid_len;                  /**< Length of the SSID */
55 	uint32_t flags;                   /**< Flags for controlling detail settings */
56 	uint32_t timeout;                 /**< Timeout for connecting to the network */
57 	uint8_t bssid[WIFI_MAC_ADDR_LEN]; /**< BSSID (Basic Service Set Identifier) */
58 	uint8_t channel;                  /**< Channel on which the network operates */
59 };
60 
61 /**
62  * @brief Wi-Fi Personal credentials entry
63  * @note Contains only the header and a password.
64  *       For PSK security, passwords can be up to `WIFI_PSK_MAX_LEN` bytes long
65  *       including NULL termination. For SAE security it can range up to
66  *       `CONFIG_WIFI_CREDENTIALS_SAE_PASSWORD_LENGTH`.
67  *
68  */
69 struct wifi_credentials_personal {
70 	struct wifi_credentials_header header;            /**< Header */
71 	char password[WIFI_CREDENTIALS_MAX_PASSWORD_LEN]; /**< Password/PSK */
72 	size_t password_len;                              /**< Length of the password */
73 };
74 
75 /**
76  * @brief Wi-Fi Enterprise credentials entry
77  * @note This functionality is not yet implemented.
78  */
79 struct wifi_credentials_enterprise {
80 	struct wifi_credentials_header header; /**< Header */
81 	size_t identity_len;                   /**< Length of the identity */
82 	size_t anonymous_identity_len;         /**< Length of the anonymous identity */
83 	size_t password_len;                   /**< Length of the password */
84 	size_t ca_cert_len;                    /**< Length of the CA certificate */
85 	size_t client_cert_len;                /**< Length of the client certificate */
86 	size_t private_key_len;                /**< Length of the private key */
87 	size_t private_key_pw_len;             /**< Length of the private key password */
88 };
89 
90 /**
91  * @brief Get credentials for given SSID.
92  *
93  * @param[in] ssid			SSID to look for
94  * @param[in] ssid_len			length of SSID
95  * @param[out] type			Wi-Fi security type
96  * @param[out] bssid_buf		buffer to store BSSID if it was fixed
97  * @param[in] bssid_buf_len		length of bssid_buf
98  * @param[out] password_buf		buffer to store password
99  * @param[in] password_buf_len		length of password_buf
100  * @param[out] password_len		length of password
101  * @param[out] flags			flags
102  * @param[out] channel			channel
103  * @param[out] timeout			timeout
104  *
105  * @return 0		Success.
106  * @return -ENOENT	No network with this SSID was found.
107  * @return -EINVAL	A required buffer was NULL or invalid SSID length.
108  * @return -EPROTO	The network with this SSID is not a personal network.
109  */
110 int wifi_credentials_get_by_ssid_personal(const char *ssid, size_t ssid_len,
111 					  enum wifi_security_type *type, uint8_t *bssid_buf,
112 					  size_t bssid_buf_len, char *password_buf,
113 					  size_t password_buf_len, size_t *password_len,
114 					  uint32_t *flags, uint8_t *channel, uint32_t *timeout);
115 
116 /**
117  * @brief Set credentials for given SSID.
118  *
119  * @param[in] ssid		SSID to look for
120  * @param[in] ssid_len		length of SSID
121  * @param[in] type		Wi-Fi security type
122  * @param[in] bssid		BSSID (may be NULL)
123  * @param[in] bssid_len		length of BSSID buffer (either 0 or WIFI_MAC_ADDR_LEN)
124  * @param[in] password		password
125  * @param[in] password_len		length of password
126  * @param[in] flags			flags
127  * @param[in] channel			Channel
128  * @param[in] timeout			Timeout
129  *
130  * @return 0			Success. Credentials are stored in persistent storage.
131  * @return -EINVAL		A required buffer was NULL or security type is not supported.
132  * @return -ENOTSUP		Security type is not supported.
133  * @return -ENOBUFS		All slots are already taken.
134  */
135 int wifi_credentials_set_personal(const char *ssid, size_t ssid_len, enum wifi_security_type type,
136 				  const uint8_t *bssid, size_t bssid_len, const char *password,
137 				  size_t password_len, uint32_t flags, uint8_t channel,
138 				  uint32_t timeout);
139 
140 /**
141  * @brief Get credentials for given SSID by struct.
142  *
143  * @param[in] ssid		SSID to look for
144  * @param[in] ssid_len		length of SSID
145  * @param[out] buf		credentials Pointer to struct where credentials are stored
146  *
147  * @return 0			Success.
148  * @return -ENOENT		No network with this SSID was found.
149  * @return -EINVAL		A required buffer was NULL or too small.
150  * @return -EPROTO		The network with this SSID is not a personal network.
151  */
152 int wifi_credentials_get_by_ssid_personal_struct(const char *ssid, size_t ssid_len,
153 						 struct wifi_credentials_personal *buf);
154 
155 /**
156  * @brief Set credentials for given SSID by struct.
157  *
158  * @param[in] creds		credentials Pointer to struct from which credentials are loaded
159  *
160  * @return 0			Success.
161  * @return -ENOENT		No network with this SSID was found.
162  * @return -EINVAL		A required buffer was NULL or incorrect size.
163  * @return -ENOBUFS		All slots are already taken.
164  */
165 int wifi_credentials_set_personal_struct(const struct wifi_credentials_personal *creds);
166 
167 /**
168  * @brief Delete credentials for given SSID.
169  *
170  * @param[in] ssid		SSID to look for
171  * @param[in] ssid_len		length of SSID
172  *
173  * @return			-ENOENT if No network with this SSID was found.
174  * @return			0 on success, otherwise a negative error code
175  */
176 int wifi_credentials_delete_by_ssid(const char *ssid, size_t ssid_len);
177 
178 /**
179  * @brief Check if credentials storage is empty.
180  *
181  * @return			true if credential storage is empty, otherwise false
182  */
183 bool wifi_credentials_is_empty(void);
184 
185 /**
186  * @brief Deletes all stored Wi-Fi credentials.
187  *
188  * This function deletes all Wi-Fi credentials that have been stored in the system.
189  * It is typically used when you want to clear all saved networks.
190  *
191  * @return			0 on successful, otherwise a negative error code
192  */
193 int wifi_credentials_delete_all(void);
194 
195 /**
196  * @brief Callback type for wifi_credentials_for_each_ssid.
197  * @param[in] cb_arg      arguments for the callback function. Appropriate cb_arg is
198  *                        transferred by wifi_credentials_for_each_ssid.
199  * @param[in] ssid        SSID
200  * @param[in] ssid_len    length of SSID
201  */
202 typedef void (*wifi_credentials_ssid_cb)(void *cb_arg, const char *ssid, size_t ssid_len);
203 
204 /**
205  * @brief Call callback for each registered SSID.
206  *
207  * @param cb		callback
208  * @param cb_arg	argument for callback function
209  */
210 void wifi_credentials_for_each_ssid(wifi_credentials_ssid_cb cb, void *cb_arg);
211 
212 #ifdef __cplusplus
213 }
214 #endif
215 
216 /** @} */
217 
218 #endif /* WIFI_CREDENTIALS_H__ */
219