Skip to content

Commit 2f256f7

Browse files
committed
libraries/SocketWrapper: Support loading CA certs from the file system.
This patch adds support for automatically loading CA certificates from the filesystem. The file system certs are loaded on the first call to connectSSL(), once, and shared between all sockets. If filesystem support is not enabled, or CA loading fails, the connection proceeds without error. Custom CA certificates can still be passed via the 'cert' parameter, and both filesystem and custom certificates are registered with using different TLS tags. This allows users to add their own certs without recreating the whole file. Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
1 parent ac15a3f commit 2f256f7

File tree

1 file changed

+73
-10
lines changed

1 file changed

+73
-10
lines changed

libraries/SocketWrapper/SocketWrapper.h

Lines changed: 73 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
#pragma once
22

33
#include "zephyr/sys/printk.h"
4+
#if defined(CONFIG_FILE_SYSTEM)
5+
#include <zephyr/fs/fs.h>
6+
#endif
7+
48
#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
59
#include <zephyr/net/tls_credentials.h>
6-
#define CA_CERTIFICATE_TAG 1
10+
#define CA_CERTIFICATE_TAG_BASE 1
711
#endif
812

913
#include <zephyr/net/socket.h>
@@ -14,6 +18,47 @@ class ZephyrSocketWrapper {
1418
bool is_ssl = false;
1519
int ssl_sock_temp_char = -1;
1620

21+
#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) && defined(CONFIG_FILE_SYSTEM)
22+
inline static char *cadata = nullptr;
23+
24+
bool loadCADataFromFS(const char *cert_path = "/wlan:/cacert.pem") {
25+
struct fs_file_t file;
26+
fs_file_t_init(&file);
27+
28+
if (fs_open(&file, cert_path, FS_O_READ) != 0) {
29+
return false;
30+
}
31+
32+
// Get file size
33+
struct fs_dirent entry;
34+
if (fs_stat(cert_path, &entry) != 0) {
35+
fs_close(&file);
36+
return false;
37+
}
38+
39+
size_t file_size = entry.size;
40+
41+
// Allocate buffer for entire file
42+
cadata = (char *)k_malloc(file_size);
43+
if (!cadata) {
44+
fs_close(&file);
45+
return false;
46+
}
47+
48+
// Read entire file
49+
ssize_t bytes_read = fs_read(&file, cadata, file_size);
50+
fs_close(&file);
51+
52+
if (bytes_read != file_size) {
53+
k_free(cadata);
54+
cadata = nullptr;
55+
return false;
56+
}
57+
58+
return true;
59+
}
60+
#endif
61+
1762
public:
1863
ZephyrSocketWrapper() : sock_fd(-1) {
1964
}
@@ -102,7 +147,7 @@ class ZephyrSocketWrapper {
102147
}
103148

104149
#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
105-
bool connectSSL(const char *host, uint16_t port, const char *ca_certificate_pem = nullptr) {
150+
bool connectSSL(const char *host, uint16_t port, const char *cert = nullptr) {
106151

107152
// Resolve address
108153
struct addrinfo hints = {0};
@@ -115,9 +160,9 @@ class ZephyrSocketWrapper {
115160
int ret;
116161
bool rv = false;
117162

118-
sec_tag_t sec_tag_opt[] = {
119-
CA_CERTIFICATE_TAG,
120-
};
163+
sec_tag_t sec_tag_opt[2];
164+
int tag_count = 0;
165+
int tag = CA_CERTIFICATE_TAG_BASE;
121166

122167
struct timeval timeout_opt = {
123168
.tv_sec = 0,
@@ -138,21 +183,39 @@ class ZephyrSocketWrapper {
138183
goto exit;
139184
}
140185

141-
if (ca_certificate_pem != nullptr) {
142-
ret = tls_credential_add(CA_CERTIFICATE_TAG, TLS_CREDENTIAL_CA_CERTIFICATE,
143-
ca_certificate_pem, strlen(ca_certificate_pem) + 1);
144-
if (ret != 0) {
186+
#if defined(CONFIG_FILE_SYSTEM)
187+
// Try to load builtin CA from filesystem (once)
188+
if (cadata == nullptr && loadCADataFromFS()) {
189+
// Successfully loaded, add with tag (ignore errors)
190+
if (tls_credential_add(tag++, TLS_CREDENTIAL_CA_CERTIFICATE, cadata,
191+
strlen(cadata) + 1)) {
145192
goto exit;
146193
}
147194
}
195+
#endif
196+
197+
// Add custom CA if provided (uses next available tag)
198+
if (cert != nullptr) {
199+
if (tls_credential_add(tag++, TLS_CREDENTIAL_CA_CERTIFICATE, cert, strlen(cert) + 1) !=
200+
0) {
201+
goto exit;
202+
}
203+
}
204+
205+
// Build sequential tag list
206+
tag_count = tag - CA_CERTIFICATE_TAG_BASE;
207+
for (int i = 0; i < tag_count; i++) {
208+
sec_tag_opt[i] = CA_CERTIFICATE_TAG_BASE + i;
209+
}
148210

149211
sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TLS_1_2);
150212
if (sock_fd < 0) {
151213
goto exit;
152214
}
153215

154216
if (setsockopt(sock_fd, SOL_TLS, TLS_HOSTNAME, host, strlen(host)) ||
155-
setsockopt(sock_fd, SOL_TLS, TLS_SEC_TAG_LIST, sec_tag_opt, sizeof(sec_tag_opt)) ||
217+
setsockopt(sock_fd, SOL_TLS, TLS_SEC_TAG_LIST, sec_tag_opt,
218+
sizeof(sec_tag_t) * tag_count) ||
156219
setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout_opt, sizeof(timeout_opt))) {
157220
goto exit;
158221
}

0 commit comments

Comments
 (0)