net: lwip: add support for built-in root certificates
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>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 764de48..cd391d4 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2184,6 +2184,20 @@
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 1152c94..58c10fb 100644
--- a/cmd/net-lwip.c
+++ b/cmd/net-lwip.c
@@ -41,6 +41,10 @@
" - 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 79dd6b3..950c531 100644
--- a/net/lwip/Makefile
+++ b/net/lwip/Makefile
@@ -6,3 +6,9 @@
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 c22843e..ec09814 100644
--- a/net/lwip/wget.c
+++ b/net/lwip/wget.c
@@ -304,28 +304,34 @@
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,9 +346,31 @@
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)
{
@@ -373,8 +401,15 @@
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 @@
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")))