[PATCH v2 1/6] net: lwip: extend wget to support CA (root) certificates
Heinrich Schuchardt
xypron.glpk at gmx.de
Wed Mar 5 16:07:42 CET 2025
On 05.03.25 15:26, Jerome Forissier wrote:
> Add the "cacert" (Certification Authority certificates) subcommand to
> wget to pass root certificates to the code handling the HTTPS protocol.
> The subcommand is enabled by the WGET_CACERT Kconfig symbol.
>
> Usage example:
>
> => dhcp
> # Download some root certificates (note: not authenticated!)
> => wget https://cacerts.digicert.com/DigiCertTLSECCP384RootG5.crt
> # Provide root certificates
> => wget cacert $fileaddr $filesize
> # Enforce verification (it is optional by default)
> => wget cacert required
> # Forget the root certificates
> => wget cacert 0 0
> # Disable verification
> => wget cacert none
>
> Signed-off-by: Jerome Forissier <jerome.forissier at linaro.org>
> ---
> cmd/Kconfig | 8 ++++
> cmd/net-lwip.c | 17 ++++++--
> net/lwip/wget.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++--
> 3 files changed, 121 insertions(+), 6 deletions(-)
>
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index 8dd42571abc..d469217c0ea 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -2177,6 +2177,14 @@ config WGET_HTTPS
> help
> Enable TLS over http for wget.
>
> +config WGET_CACERT
> + bool "wget cacert"
> + depends on CMD_WGET
> + depends on WGET_HTTPS
> + help
> + Adds the "cacert" sub-command to wget to provide root certificates
> + to the HTTPS engine. Must be in DER format.
> +
Shouldn't we build CA certs into U-Boot?
Downloading certs from unsafe media is not a good replacement.
Best regards
Heinrich
> endif # if CMD_NET
>
> config CMD_PXE
> diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
> index 0fd446ecb20..1152c94a6dc 100644
> --- a/cmd/net-lwip.c
> +++ b/cmd/net-lwip.c
> @@ -27,9 +27,20 @@ U_BOOT_CMD(dns, 3, 1, do_dns, "lookup the IP of a hostname",
> #endif
>
> #if defined(CONFIG_CMD_WGET)
> -U_BOOT_CMD(wget, 3, 1, do_wget,
> - "boot image via network using HTTP/HTTPS protocol",
> +U_BOOT_CMD(wget, 4, 1, do_wget,
> + "boot image via network using HTTP/HTTPS protocol"
> +#if defined(CONFIG_WGET_CACERT)
> + "\nwget cacert - configure wget root certificates"
> +#endif
> + ,
> "[loadAddress] url\n"
> - "wget [loadAddress] [host:]path"
> + "wget [loadAddress] [host:]path\n"
> + " - load file"
> +#if defined(CONFIG_WGET_CACERT)
> + "\nwget cacert <address> <length>\n"
> + " - provide CA certificates (0 0 to remove current)"
> + "\nwget cacert none|optional|required\n"
> + " - set server certificate verification mode (default: optional)"
> +#endif
> );
> #endif
> diff --git a/net/lwip/wget.c b/net/lwip/wget.c
> index 14f27d42998..c22843ee10d 100644
> --- a/net/lwip/wget.c
> +++ b/net/lwip/wget.c
> @@ -285,9 +285,68 @@ static err_t httpc_headers_done_cb(httpc_state_t *connection, void *arg, struct
> return ERR_OK;
> }
>
> +#if CONFIG_IS_ENABLED(WGET_HTTPS)
> +enum auth_mode {
> + AUTH_NONE,
> + AUTH_OPTIONAL,
> + AUTH_REQUIRED,
> +};
> +
> +static char *cacert;
> +static size_t cacert_size;
> +static enum auth_mode cacert_auth_mode = AUTH_OPTIONAL;
> +#endif
> +
> +#if CONFIG_IS_ENABLED(WGET_CACERT)
> +static int set_auth(enum auth_mode auth)
> +{
> + cacert_auth_mode = auth;
> +
> + return CMD_RET_SUCCESS;
> +}
> +
> +static int set_cacert(char * const saddr, char * const ssz)
> +{
> + mbedtls_x509_crt crt;
> + ulong addr, sz;
> + 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)
> + return CMD_RET_FAILURE;
> + cacert_size = sz;
> +
> + memcpy(cacert, (void *)addr, sz);
> +
> + mbedtls_x509_crt_init(&crt);
> + ret = mbedtls_x509_crt_parse(&crt, cacert, cacert_size);
> + if (ret) {
> + printf("Could not parse certificates (%d)\n", ret);
> + free(cacert);
> + cacert = NULL;
> + cacert_size = 0;
> + return CMD_RET_FAILURE;
> + }
> +
> + return CMD_RET_SUCCESS;
> +}
> +#endif
> +
> static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri)
> {
> -#if defined CONFIG_WGET_HTTPS
> +#if CONFIG_IS_ENABLED(WGET_HTTPS)
> altcp_allocator_t tls_allocator;
> #endif
> httpc_connection_t conn;
> @@ -312,11 +371,34 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri)
> return -1;
>
> memset(&conn, 0, sizeof(conn));
> -#if defined CONFIG_WGET_HTTPS
> +#if CONFIG_IS_ENABLED(WGET_HTTPS)
> if (is_https) {
> + char *ca = cacert;
> + size_t ca_sz = cacert_size;
> +
> + if (cacert_auth_mode == AUTH_REQUIRED) {
> + if (!ca || !ca_sz) {
> + printf("Error: cacert authentication mode is "
> + "'required' but no CA certificates "
> + "given\n");
> + return CMD_RET_FAILURE;
> + }
> + } else if (cacert_auth_mode == AUTH_NONE) {
> + ca = NULL;
> + ca_sz = 0;
> + } else if (cacert_auth_mode == AUTH_OPTIONAL) {
> + /*
> + * Nothing to do, this is the default behavior of
> + * altcp_tls to check server certificates against CA
> + * certificates when the latter are provided and proceed
> + * with no verification if not.
> + */
> + }
> +
> tls_allocator.alloc = &altcp_tls_alloc;
> tls_allocator.arg =
> - altcp_tls_create_config_client(NULL, 0, ctx.server_name);
> + altcp_tls_create_config_client(ca, ca_sz,
> + ctx.server_name);
>
> if (!tls_allocator.arg) {
> log_err("error: Cannot create a TLS connection\n");
> @@ -369,6 +451,20 @@ int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
> ulong dst_addr;
> char nurl[1024];
>
> +#if CONFIG_IS_ENABLED(WGET_CACERT)
> + 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 (!strncmp(argv[2], "none", strlen("none")))
> + return set_auth(AUTH_NONE);
> + if (!strncmp(argv[2], "optional", strlen("optional")))
> + return set_auth(AUTH_OPTIONAL);
> + if (!strncmp(argv[2], "required", strlen("required")))
> + return set_auth(AUTH_REQUIRED);
> + return CMD_RET_USAGE;
> + }
> +#endif
> +
> if (argc < 2 || argc > 3)
> return CMD_RET_USAGE;
>
More information about the U-Boot
mailing list