Sorry for replying to myself, I spotted a small mistake.

On 2/27/25 17:09, Jerome Forissier wrote:
> Introduce Kconfig symbols WGET_BUILTIN_CACERT and
> WGET_BUILTIN_CACERT_PATH to provide root certificates at build time. The
> file may be a DER-encoded (.crt) or PEM-encoded (.pem) X509 collection
> of one or more certificates. PEM encoding needs MBEDTLS_LIB_X509_PEM.
> 
> Usage example:
> 
>  wget https://curl.se/ca/cacert.pem
>  make qemu_arm64_lwip_defconfig
>  echo CONFIG_WGET_BUILTIN_CACERT=y >>.config
>  echo CONFIG_WGET_BUILTIN_CACERT_PATH=cacert.pem >>.config
>  echo CONFIG_MBEDTLS_LIB_X509_PEM=y >>.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://www.google.com/
>  18724 bytes transferred in 15 ms (1.2 MiB/s)
>  Bytes transferred = 18724 (4924 hex)
> 
> Signed-off-by: Jerome Forissier <jerome.foriss...@linaro.org>
> ---
>  cmd/Kconfig       | 16 +++++++++++++-
>  cmd/net-lwip.c    |  4 ++++
>  net/lwip/Makefile |  6 ++++++
>  net/lwip/wget.c   | 53 +++++++++++++++++++++++++++++++++++++++--------
>  4 files changed, 69 insertions(+), 10 deletions(-)
> 
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index a188a2ef24b..cb3cc859616 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -2186,12 +2186,26 @@ config WGET_CACERT
>         to the HTTPS engine.
>  
>  config MBEDTLS_LIB_X509_PEM
> -     depends on WGET_CACERT
> +     depends on WGET_HTTPS
>       bool "Support for PEM-encoded X509 certificates"
>       help
>         This option enables MbedTLS to parse PEM-encoded X509 certificates.
>         When disabled, only DER format is accepted.
>  
> +config WGET_BUILTIN_CACERT
> +     bool "Built-in CA certificates"
> +     depends on WGET_HTTPS
> +
> +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- or PEM-encoded X509 file containing
> +       Certification Authority certificates, a.k.a. root certificates, for
> +       the purpose of authenticating HTTPS connections. Do not forget to
> +       enable MBEDTLS_LIB_X509_PEM if the file is PEM.
> +
>  endif  # if CMD_NET
>  
>  config CMD_PXE
> diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
> index 0672f48a7a8..a848d0b1dcf 100644
> --- a/cmd/net-lwip.c
> +++ b/cmd/net-lwip.c
> @@ -39,6 +39,10 @@ U_BOOT_CMD(wget, 4, 1, do_wget,
>  #if defined(CONFIG_WGET_CACERT)
>          "\nwget cacert <address> <length>\n"
>          "    - provide CA certificates (0 0 to disable verification)"
> +#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 14466598d7c..f24aa9c2380 100644
> --- a/net/lwip/wget.c
> +++ b/net/lwip/wget.c
> @@ -288,31 +288,34 @@ static err_t httpc_headers_done_cb(httpc_state_t 
> *connection, void *arg, struct
>  #if defined CONFIG_WGET_HTTPS
>  static char *cacert;
>  size_t cacert_size;
> +
> +#if defined CONFIG_WGET_BUILTIN_CACERT
> +extern char builtin_cacert[];
> +extern const size_t builtin_cacert_size;
> +static bool cacert_initialized;
> +#endif
>  #endif
>  
> -#if defined CONFIG_WGET_CACERT
> -static int set_cacert(char * const saddr, char * const ssz)
> +#if defined CONFIG_WGET_CACERT || defined CONFIG_WGET_BUILTIN_CACERT
> +static int _set_cacert(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);
> -     sz++; /* For the trailing '\0' in case of a text (PEM) file */
> -
>       if (!addr) {
>               cacert = NULL;
>               cacert_size = 0;
>               return CMD_RET_SUCCESS;
>       }
>  
> -     cacert = malloc(sz);
> -     if (!cacert)

HERE...

> +     p = malloc(sz);
> +     if (!p)
>               return CMD_RET_FAILURE;
> +     cacert = p;
>       cacert_size = sz;
>  
>       memcpy(cacert, (void *)addr, sz - 1);
> @@ -328,10 +331,33 @@ static int set_cacert(char * const saddr, char * const 
> ssz)
>               return CMD_RET_FAILURE;
>       }
>  
> +#if defined CONFIG_WGET_BUILTIN_CACERT
> +     cacert_initialized = true;
> +#endif
>       return CMD_RET_SUCCESS;
>  }
> +
> +#if defined CONFIG_WGET_BUILTIN_CACERT
> +static int set_cacert_builtin(void)
> +{
> +     return _set_cacert(builtin_cacert, builtin_cacert_size);
> +}
>  #endif
>  
> +#if defined CONFIG_WGET_CACERT
> +static int set_cacert(char * const saddr, char * const ssz)
> +{
> +     ulong addr, sz;
> +
> +     addr = hextoul(saddr, NULL);
> +     sz = hextoul(ssz, NULL);
> +     sz++; /* For the trailing '\0' in case of a text (PEM) file */

This line should have been moved to _set_cacert() at the place I marked
"HERE" above.

The reason for this hack is, before even attempting to parse a file as
PEM format (which is text-based), mbedtls_x509_crt_parse() checks that
buf[buflen - 1] == '\0'. When a text file is obtained via wget there is
no null terminator. Same when using bin2c. So adding the '\0' is
necessary.

I decided to always add a null byte because it appears to not cause any
problem with binary (DER) files anyways.

> +
> +     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 defined CONFIG_WGET_HTTPS
> @@ -361,6 +387,10 @@ static int wget_loop(struct udevice *udev, ulong 
> dst_addr, char *uri)
>       memset(&conn, 0, sizeof(conn));
>  #if defined CONFIG_WGET_HTTPS
>       if (is_https) {
> +#if defined CONFIG_WGET_BUILTIN_CACERT
> +             if (!cacert_initialized)
> +                     set_cacert_builtin();
> +#endif
>               tls_allocator.alloc = &altcp_tls_alloc;
>               tls_allocator.arg =
>                       altcp_tls_create_config_client(cacert, cacert_size,
> @@ -420,6 +450,11 @@ int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, 
> char * const argv[])
>  #if defined CONFIG_WGET_CACERT
>       if (argc == 4 && !strncmp(argv[1], "cacert", strlen("cacert")))
>               return set_cacert(argv[2], argv[3]);
> +#if defined CONFIG_WGET_BUILTIN_CACERT
> +     if (argc == 3 && !strncmp(argv[1], "cacert", strlen("cacert")) &&
> +         !strncmp(argv[2], "builtin", strlen("builtin")))
> +             return set_cacert_builtin();
> +#endif
>  #endif
>  
>       if (argc < 2 || argc > 3)

Reply via email to