Skip to content

Commit d27d08e

Browse files
committed
[nrf fromlist] net: l2: wifi: Add support for run-time certificates
Using TLS credentials library add support for run-time certificates where the installed certs are retrieved from the credential store (as of now only volatile backend is tested). This helps in production environments. Implements #79564. Upstream PR #: 87656 Signed-off-by: Chaitanya Tata <[email protected]>
1 parent b1b4a66 commit d27d08e

File tree

3 files changed

+280
-26
lines changed

3 files changed

+280
-26
lines changed

doc/connectivity/networking/api/wifi.rst

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,15 @@ Wi-Fi PSA crypto supported build
3030

3131
To enable PSA crypto API supported Wi-Fi build, the :kconfig:option:`CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ALT` and the :kconfig:option:`CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_MBEDTLS_PSA` need to be set.
3232

33-
Wi-Fi Enterprise test: X.509 Certificate header generation
34-
**********************************************************
33+
Wi-Fi Enterprise test: X.509 Certificate management
34+
***************************************************
3535

36-
Wi-Fi enterprise security requires use of X.509 certificates, test certificates
37-
in PEM format are committed to the repo at :zephyr_file:`samples/net/wifi/test_certs` and the during the
36+
Wi-Fi enterprise security requires use of X.509 certificates, two methods of installing certificates are supported:
37+
38+
Compile time certificates
39+
-------------------------
40+
41+
Test certificates in PEM format are committed to the repo at :zephyr_file:`samples/net/wifi/test_certs` and the during the
3842
build process the certificates are converted to a C header file that is included by the Wi-Fi shell
3943
module.
4044

@@ -55,6 +59,12 @@ For using variable size network buffer, the following overlay file can be used:
5559
$ west build -p -b <board> samples/net/wifi -- -DEXTRA_CONF_FILE=overlay-enterprise-variable-bufs.conf
5660
5761
62+
Run time certificates
63+
---------------------
64+
65+
The Wi-Fi shell module uses TLS credentials subsystem to store and manage the certificates. The certificates can be added at runtime using the shell commands, see :ref:`tls_credentials_shell` for more details.
66+
The sample or application need to enable the :kconfig:option:`CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES` option to use this feature.
67+
5868

5969
To initiate Wi-Fi connection, the following command can be used:
6070

subsys/net/l2/wifi/Kconfig

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,23 @@ config WIFI_ENT_IDENTITY_MAX_USERS
125125
default 8
126126
help
127127
This option defines the maximum number of identity users allowed connection.
128+
129+
if WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
130+
131+
config WIFI_SHELL_RUNTIME_CERTIFICATES
132+
bool "Provide Wi-Fi enterprise security certificates at run-time"
133+
select TLS_CREDENTIALS
134+
select TLS_CREDENTIALS_SHELL
135+
select BASE64
136+
help
137+
This option enables providing Wi-Fi enterprise security certificates at run-time.
138+
Uses the TLS credentials subsystem to store and manage the certificates.
139+
140+
config HEAP_MEM_POOL_ADD_SIZE_WIFI_CERT
141+
int "Wi-Fi enterprise security certificates memory pool size"
142+
# STA - 6 certs and each assume 1500 bytes
143+
default 12000
144+
help
145+
The size of the memory pool used by the Wi-Fi enterprise security certificates.
146+
147+
endif # WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE

subsys/net/l2/wifi/wifi_shell.c

Lines changed: 246 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,29 @@ LOG_MODULE_REGISTER(net_wifi_shell, LOG_LEVEL_INF);
3030

3131
#include "net_shell_private.h"
3232
#include <math.h>
33-
#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
33+
#if defined CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE || \
34+
defined CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE
35+
#ifdef CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES
36+
#include <zephyr/net/tls_credentials.h>
37+
enum wifi_enterprise_cert_sec_tags {
38+
WIFI_CERT_CA_SEC_TAG = 0x1020001,
39+
WIFI_CERT_CLIENT_KEY_SEC_TAG,
40+
WIFI_CERT_SERVER_KEY_SEC_TAG,
41+
WIFI_CERT_CLIENT_SEC_TAG,
42+
WIFI_CERT_SERVER_SEC_TAG,
43+
/* Phase 2 */
44+
WIFI_CERT_CA_P2_SEC_TAG,
45+
WIFI_CERT_CLIENT_KEY_P2_SEC_TAG,
46+
WIFI_CERT_CLIENT_P2_SEC_TAG,
47+
};
48+
49+
struct wifi_cert_data {
50+
enum tls_credential_type type;
51+
uint32_t sec_tag;
52+
uint8_t **data;
53+
size_t *len;
54+
};
55+
#else
3456
static const char ca_cert_test[] = {
3557
#include <wifi_enterprise_test_certs/ca.pem.inc>
3658
'\0'
@@ -67,7 +89,8 @@ static const char server_key_test[] = {
6789
#include <wifi_enterprise_test_certs/server-key.pem.inc>
6890
'\0'
6991
};
70-
#endif
92+
#endif /* CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES */
93+
#endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE */
7194

7295
#define WIFI_SHELL_MODULE "wifi"
7396

@@ -102,6 +125,12 @@ static struct {
102125
};
103126
uint8_t all;
104127
};
128+
#if defined CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE || \
129+
defined CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE
130+
#ifdef CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES
131+
struct wifi_enterprise_creds_params enterprise_creds_params;
132+
#endif /* CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES */
133+
#endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE */
105134
} context;
106135

107136
static struct net_mgmt_event_callback wifi_shell_mgmt_cb;
@@ -117,27 +146,211 @@ static struct wifi_ap_sta_node sta_list[CONFIG_WIFI_SHELL_MAX_AP_STA];
117146

118147
#if defined CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE || \
119148
defined CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE
120-
static int cmd_wifi_set_enterprise_creds(const struct shell *sh, struct net_if *iface)
149+
#ifdef CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES
150+
static int process_certificates(struct wifi_cert_data *certs, size_t cert_count)
151+
{
152+
for (size_t i = 0; i < cert_count; i++) {
153+
int err;
154+
size_t len = 0;
155+
uint8_t *cert_tmp;
156+
157+
err = tls_credential_get(certs[i].sec_tag, certs[i].type, NULL, &len);
158+
if (err != -EFBIG) {
159+
LOG_ERR("Failed to get credential tag: %d length, err: %d",
160+
certs[i].sec_tag, err);
161+
return err;
162+
}
163+
164+
cert_tmp = k_malloc(len);
165+
if (!cert_tmp) {
166+
LOG_ERR("Failed to allocate memory for credential tag: %d",
167+
certs[i].sec_tag);
168+
return -ENOMEM;
169+
}
170+
171+
err = tls_credential_get(certs[i].sec_tag, certs[i].type, cert_tmp, &len);
172+
if (err) {
173+
LOG_ERR("Failed to get credential tag: %d", certs[i].sec_tag);
174+
k_free(cert_tmp);
175+
return err;
176+
}
177+
178+
*certs[i].data = cert_tmp;
179+
*certs[i].len = len;
180+
}
181+
182+
return 0;
183+
}
184+
185+
static void set_enterprise_creds_params(struct wifi_enterprise_creds_params *params,
186+
bool is_ap)
121187
{
122-
struct wifi_enterprise_creds_params params = {0};
188+
struct wifi_cert_data certs_common[] = {
189+
{
190+
.type = TLS_CREDENTIAL_CA_CERTIFICATE,
191+
.sec_tag = WIFI_CERT_CA_SEC_TAG,
192+
.data = &params->ca_cert,
193+
.len = &params->ca_cert_len,
194+
},
195+
};
196+
197+
struct wifi_cert_data certs_sta[] = {
198+
{
199+
.type = TLS_CREDENTIAL_PRIVATE_KEY,
200+
.sec_tag = WIFI_CERT_CLIENT_KEY_SEC_TAG,
201+
.data = &params->client_key,
202+
.len = &params->client_key_len,
203+
},
204+
{
205+
.type = TLS_CREDENTIAL_PUBLIC_CERTIFICATE,
206+
.sec_tag = WIFI_CERT_CLIENT_SEC_TAG,
207+
.data = &params->client_cert,
208+
.len = &params->client_cert_len,
209+
},
210+
{
211+
.type = TLS_CREDENTIAL_CA_CERTIFICATE,
212+
.sec_tag = WIFI_CERT_CA_P2_SEC_TAG,
213+
.data = &params->ca_cert2,
214+
.len = &params->ca_cert2_len,
215+
},
216+
{
217+
.type = TLS_CREDENTIAL_PRIVATE_KEY,
218+
.sec_tag = WIFI_CERT_CLIENT_KEY_P2_SEC_TAG,
219+
.data = &params->client_key2,
220+
.len = &params->client_key2_len,
221+
},
222+
{
223+
.type = TLS_CREDENTIAL_PUBLIC_CERTIFICATE,
224+
.sec_tag = WIFI_CERT_CLIENT_P2_SEC_TAG,
225+
.data = &params->client_cert2,
226+
.len = &params->client_cert2_len,
227+
},
228+
};
229+
230+
struct wifi_cert_data certs_ap[] = {
231+
{
232+
.type = TLS_CREDENTIAL_PUBLIC_CERTIFICATE,
233+
.sec_tag = WIFI_CERT_SERVER_SEC_TAG,
234+
.data = &params->server_cert,
235+
.len = &params->server_cert_len,
236+
},
237+
{
238+
.type = TLS_CREDENTIAL_PRIVATE_KEY,
239+
.sec_tag = WIFI_CERT_SERVER_KEY_SEC_TAG,
240+
.data = &params->server_key,
241+
.len = &params->server_key_len,
242+
},
243+
};
244+
245+
memset(params, 0, sizeof(*params));
246+
247+
/* Process common certificates */
248+
if (process_certificates(certs_common, ARRAY_SIZE(certs_common)) != 0) {
249+
goto cleanup;
250+
}
251+
252+
/* Process STA-specific certificates */
253+
if (!is_ap) {
254+
if (process_certificates(certs_sta, ARRAY_SIZE(certs_sta)) != 0) {
255+
goto cleanup;
256+
}
257+
}
258+
259+
/* Process AP-specific certificates if is_ap is true */
260+
if (is_ap) {
261+
if (process_certificates(certs_ap, ARRAY_SIZE(certs_ap)) != 0) {
262+
goto cleanup;
263+
}
264+
}
265+
266+
memcpy(&context.enterprise_creds_params, params, sizeof(*params));
267+
return;
268+
269+
cleanup:
270+
for (size_t i = 0; i < ARRAY_SIZE(certs_common); i++) {
271+
if (certs_common[i].data) {
272+
k_free(*certs_common[i].data);
273+
}
274+
}
275+
276+
if (!is_ap) {
277+
for (size_t i = 0; i < ARRAY_SIZE(certs_sta); i++) {
278+
if (certs_sta[i].data) {
279+
k_free(*certs_sta[i].data);
280+
}
281+
}
282+
}
123283

124-
params.ca_cert = (uint8_t *)ca_cert_test;
125-
params.ca_cert_len = ARRAY_SIZE(ca_cert_test);
126-
params.client_cert = (uint8_t *)client_cert_test;
127-
params.client_cert_len = ARRAY_SIZE(client_cert_test);
128-
params.client_key = (uint8_t *)client_key_test;
129-
params.client_key_len = ARRAY_SIZE(client_key_test);
130-
params.ca_cert2 = (uint8_t *)ca_cert2_test;
131-
params.ca_cert2_len = ARRAY_SIZE(ca_cert2_test);
132-
params.client_cert2 = (uint8_t *)client_cert2_test;
133-
params.client_cert2_len = ARRAY_SIZE(client_cert2_test);
134-
params.client_key2 = (uint8_t *)client_key2_test;
135-
params.client_key2_len = ARRAY_SIZE(client_key2_test);
136-
params.server_cert = (uint8_t *)server_cert_test;
137-
params.server_cert_len = ARRAY_SIZE(server_cert_test);
138-
params.server_key = (uint8_t *)server_key_test;
139-
params.server_key_len = ARRAY_SIZE(server_key_test);
284+
if (is_ap) {
285+
for (size_t i = 0; i < ARRAY_SIZE(certs_ap); i++) {
286+
if (certs_ap[i].data) {
287+
k_free(*certs_ap[i].data);
288+
}
289+
}
290+
}
291+
}
292+
293+
static void clear_enterprise_creds_params(struct wifi_enterprise_creds_params *params)
294+
{
295+
size_t i;
296+
297+
if (!params) {
298+
return;
299+
}
140300

301+
const uint8_t *certs[] = {
302+
params->ca_cert,
303+
params->client_key,
304+
params->server_cert,
305+
params->client_cert,
306+
params->ca_cert2,
307+
params->client_key2,
308+
params->client_cert2
309+
};
310+
311+
for (i = 0; i < ARRAY_SIZE(certs); i++) {
312+
k_free((void *)certs[i]);
313+
}
314+
memset(params, 0, sizeof(*params));
315+
}
316+
#else
317+
static void set_enterprise_creds_params(struct wifi_enterprise_creds_params *params,
318+
bool is_ap)
319+
{
320+
params->ca_cert = (uint8_t *)ca_cert_test;
321+
params->ca_cert_len = ARRAY_SIZE(ca_cert_test);
322+
323+
if (!is_ap) {
324+
params->client_cert = (uint8_t *)client_cert_test;
325+
params->client_cert_len = ARRAY_SIZE(client_cert_test);
326+
params->client_key = (uint8_t *)client_key_test;
327+
params->client_key_len = ARRAY_SIZE(client_key_test);
328+
params->ca_cert2 = (uint8_t *)ca_cert2_test;
329+
params->ca_cert2_len = ARRAY_SIZE(ca_cert2_test);
330+
params->client_cert2 = (uint8_t *)client_cert2_test;
331+
params->client_cert2_len = ARRAY_SIZE(client_cert2_test);
332+
params->client_key2 = (uint8_t *)client_key2_test;
333+
params->client_key2_len = ARRAY_SIZE(client_key2_test);
334+
335+
return;
336+
}
337+
338+
params->server_cert = (uint8_t *)server_cert_test;
339+
params->server_cert_len = ARRAY_SIZE(server_cert_test);
340+
params->server_key = (uint8_t *)server_key_test;
341+
params->server_key_len = ARRAY_SIZE(server_key_test);
342+
}
343+
#endif /* CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES */
344+
345+
static int wifi_set_enterprise_creds(const struct shell *sh, struct net_if *iface,
346+
bool is_ap)
347+
{
348+
struct wifi_enterprise_creds_params params = {0};
349+
350+
#ifdef CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES
351+
clear_enterprise_creds_params(&context.enterprise_creds_params);
352+
#endif /* CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES */
353+
set_enterprise_creds_params(&params, is_ap);
141354
if (net_mgmt(NET_REQUEST_WIFI_ENTERPRISE_CREDS, iface, &params, sizeof(params))) {
142355
PR_WARNING("Set enterprise credentials failed\n");
143356
return -1;
@@ -916,7 +1129,7 @@ static int cmd_wifi_connect(const struct shell *sh, size_t argc,
9161129
cnx_params.security == WIFI_SECURITY_TYPE_EAP_PEAP_GTC ||
9171130
cnx_params.security == WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2 ||
9181131
cnx_params.security == WIFI_SECURITY_TYPE_EAP_PEAP_TLS) {
919-
cmd_wifi_set_enterprise_creds(sh, iface);
1132+
wifi_set_enterprise_creds(sh, iface, 0);
9201133
}
9211134
#endif
9221135

@@ -958,6 +1171,11 @@ static int cmd_wifi_disconnect(const struct shell *sh, size_t argc,
9581171
PR("Disconnect requested\n");
9591172
}
9601173

1174+
#ifdef CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES
1175+
/* Clear the certificates */
1176+
clear_enterprise_creds_params(&context.enterprise_creds_params);
1177+
#endif /* CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES */
1178+
9611179
return 0;
9621180
}
9631181

@@ -1924,7 +2142,7 @@ static int cmd_wifi_ap_enable(const struct shell *sh, size_t argc,
19242142
cnx_params.security == WIFI_SECURITY_TYPE_EAP_PEAP_GTC ||
19252143
cnx_params.security == WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2 ||
19262144
cnx_params.security == WIFI_SECURITY_TYPE_EAP_PEAP_TLS) {
1927-
cmd_wifi_set_enterprise_creds(sh, iface);
2145+
wifi_set_enterprise_creds(sh, iface, 1);
19282146
}
19292147
#endif
19302148

@@ -1955,6 +2173,12 @@ static int cmd_wifi_ap_disable(const struct shell *sh, size_t argc,
19552173
}
19562174

19572175
PR("AP mode disable requested\n");
2176+
2177+
#ifdef CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES
2178+
/* Clear the certificates */
2179+
clear_enterprise_creds_params(&context.enterprise_creds_params);
2180+
#endif /* CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES */
2181+
19582182
return 0;
19592183
}
19602184

0 commit comments

Comments
 (0)