diff mbox series

[v2,4/6] net: lwip: add support for built-in root certificates

Message ID 20250305142650.2966738-5-jerome.forissier@linaro.org
State New
Headers show
Series net: lwip: root certificates | expand

Commit Message

Jerome Forissier March 5, 2025, 2:26 p.m. UTC
Introduce Kconfig symbols WGET_BUILTIN_CACERT and
WGET_BUILTIN_CACERT_PATH to provide root certificates at build time.

Usage example:

 wget -O cacert.crt https://cacerts.digicert.com/DigiCertTLSECCP384RootG5.crt
 make qemu_arm64_lwip_defconfig
 echo CONFIG_WGET_BUILTIN_CACERT=y >>.config
 echo CONFIG_WGET_BUILTIN_CACERT_PATH=cacert.crt >>.config
 make olddefconfig
 make -j$(nproc) CROSS_COMPILE="ccache aarch64-linux-gnu-"
 qemu-system-aarch64 -M virt -nographic -cpu max \
    -object rng-random,id=rng0,filename=/dev/urandom \
    -device virtio-rng-pci,rng=rng0 -bios u-boot.bin
 => dhcp
 # HTTPS transfer using the builtin CA certificates
 => wget https://digicert-tls-ecc-p384-root-g5.chain-demos.digicert.com/
 1867 bytes transferred in 1 ms (1.8 MiB/s)
 Bytes transferred = 1867 (74b hex)

Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
---
 cmd/Kconfig       | 14 ++++++++++++
 cmd/net-lwip.c    |  4 ++++
 net/lwip/Makefile |  6 +++++
 net/lwip/wget.c   | 57 +++++++++++++++++++++++++++++++++++++++--------
 4 files changed, 72 insertions(+), 9 deletions(-)
diff mbox series

Patch

diff --git a/cmd/Kconfig b/cmd/Kconfig
index d469217c0ea..312bf94d4e8 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2185,6 +2185,20 @@  config WGET_CACERT
 	  Adds the "cacert" sub-command to wget to provide root certificates
 	  to the HTTPS engine. Must be in DER format.
 
+config WGET_BUILTIN_CACERT
+	bool "Built-in CA certificates"
+	depends on WGET_HTTPS
+	select BUILD_BIN2C
+
+config WGET_BUILTIN_CACERT_PATH
+	string "Path to root certificates"
+	depends on WGET_BUILTIN_CACERT
+	default "cacert.crt"
+	help
+	  Set this to the path to a DER-encoded X509 file containing
+	  Certification Authority certificates, a.k.a. root certificates, for
+	  the purpose of authenticating HTTPS connections.
+
 endif  # if CMD_NET
 
 config CMD_PXE
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
index 1152c94a6dc..58c10fbec7d 100644
--- a/cmd/net-lwip.c
+++ b/cmd/net-lwip.c
@@ -41,6 +41,10 @@  U_BOOT_CMD(wget, 4, 1, do_wget,
 	   "    - provide CA certificates (0 0 to remove current)"
 	   "\nwget cacert none|optional|required\n"
 	   "    - set server certificate verification mode (default: optional)"
+#if defined(CONFIG_WGET_BUILTIN_CACERT)
+	   "\nwget cacert builtin\n"
+	   "    - use the builtin CA certificates"
+#endif
 #endif
 );
 #endif
diff --git a/net/lwip/Makefile b/net/lwip/Makefile
index 79dd6b3fb50..950c5316bb9 100644
--- a/net/lwip/Makefile
+++ b/net/lwip/Makefile
@@ -6,3 +6,9 @@  obj-$(CONFIG_CMD_DNS) += dns.o
 obj-$(CONFIG_CMD_PING) += ping.o
 obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
 obj-$(CONFIG_WGET) += wget.o
+
+ifeq (y,$(CONFIG_WGET_BUILTIN_CACERT))
+$(obj)/builtin_cacert.c: $(CONFIG_WGET_BUILTIN_CACERT_PATH:"%"=%) FORCE
+	$(call if_changed,bin2c,builtin_cacert)
+obj-y += builtin_cacert.o
+endif
diff --git a/net/lwip/wget.c b/net/lwip/wget.c
index c22843ee10d..ec098148835 100644
--- a/net/lwip/wget.c
+++ b/net/lwip/wget.c
@@ -304,28 +304,34 @@  static int set_auth(enum auth_mode auth)
 
 	return CMD_RET_SUCCESS;
 }
+#endif
 
-static int set_cacert(char * const saddr, char * const ssz)
+#if CONFIG_IS_ENABLED(WGET_BUILTIN_CACERT)
+extern const char builtin_cacert[];
+extern const size_t builtin_cacert_size;
+static bool cacert_initialized;
+#endif
+
+#if CONFIG_IS_ENABLED(WGET_CACERT) || CONFIG_IS_ENABLED(WGET_BUILTIN_CACERT)
+static int _set_cacert(const void *addr, size_t sz)
 {
 	mbedtls_x509_crt crt;
-	ulong addr, sz;
+	void *p;
 	int ret;
 
 	if (cacert)
 		free(cacert);
 
-	addr = hextoul(saddr, NULL);
-	sz = hextoul(ssz, NULL);
-
 	if (!addr) {
 		cacert = NULL;
 		cacert_size = 0;
 		return CMD_RET_SUCCESS;
 	}
 
-	cacert = malloc(sz);
-	if (!cacert)
+	p = malloc(sz);
+	if (!p)
 		return CMD_RET_FAILURE;
+	cacert = p;
 	cacert_size = sz;
 
 	memcpy(cacert, (void *)addr, sz);
@@ -340,10 +346,32 @@  static int set_cacert(char * const saddr, char * const ssz)
 		return CMD_RET_FAILURE;
 	}
 
+#if CONFIG_IS_ENABLED(WGET_BUILTIN_CACERT)
+	cacert_initialized = true;
+#endif
 	return CMD_RET_SUCCESS;
 }
+
+#if CONFIG_IS_ENABLED(WGET_BUILTIN_CACERT)
+static int set_cacert_builtin(void)
+{
+	return _set_cacert(builtin_cacert, builtin_cacert_size);
+}
 #endif
 
+#if CONFIG_IS_ENABLED(WGET_CACERT)
+static int set_cacert(char * const saddr, char * const ssz)
+{
+	ulong addr, sz;
+
+	addr = hextoul(saddr, NULL);
+	sz = hextoul(ssz, NULL);
+
+	return _set_cacert((void *)addr, sz);
+}
+#endif
+#endif  /* CONFIG_WGET_CACERT || CONFIG_WGET_BUILTIN_CACERT */
+
 static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri)
 {
 #if CONFIG_IS_ENABLED(WGET_HTTPS)
@@ -373,8 +401,15 @@  static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri)
 	memset(&conn, 0, sizeof(conn));
 #if CONFIG_IS_ENABLED(WGET_HTTPS)
 	if (is_https) {
-		char *ca = cacert;
-		size_t ca_sz = cacert_size;
+		char *ca;
+		size_t ca_sz;
+
+#if CONFIG_IS_ENABLED(WGET_BUILTIN_CACERT)
+		if (!cacert_initialized)
+			set_cacert_builtin();
+#endif
+		ca = cacert;
+		ca_sz = cacert_size;
 
 		if (cacert_auth_mode == AUTH_REQUIRED) {
 			if (!ca || !ca_sz) {
@@ -455,6 +490,10 @@  int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
 	if (argc == 4 && !strncmp(argv[1], "cacert", strlen("cacert")))
 		return set_cacert(argv[2], argv[3]);
 	if (argc == 3 && !strncmp(argv[1], "cacert", strlen("cacert"))) {
+#if CONFIG_IS_ENABLED(WGET_BUILTIN_CACERT)
+		if (!strncmp(argv[2], "builtin", strlen("builtin")))
+			return set_cacert_builtin();
+#endif
 		if (!strncmp(argv[2], "none", strlen("none")))
 			return set_auth(AUTH_NONE);
 		if (!strncmp(argv[2], "optional", strlen("optional")))