summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerome Forissier <[email protected]>2025-03-05 15:26:42 +0100
committerJerome Forissier <[email protected]>2025-03-11 14:16:03 +0100
commit2df965d385872b2ae49a79c2cab4679a8999467f (patch)
tree98e155e93f866b6376f1474e232085b7937e7d1f
parent64ce9bfc6d53423d4f6d382837a33c3dffb152af (diff)
net: lwip: extend wget to support CA (root) certificates
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 <[email protected]> Reviewed-by: Ilias Apalodimas <[email protected]>
-rw-r--r--cmd/Kconfig8
-rw-r--r--cmd/net-lwip.c17
-rw-r--r--net/lwip/wget.c102
3 files changed, 121 insertions, 6 deletions
diff --git a/cmd/Kconfig b/cmd/Kconfig
index bfed141914a..764de482890 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2176,6 +2176,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.
+
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;