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 <jerome.forissier@linaro.org> Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
This commit is contained in:
@@ -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
|
||||
|
@@ -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
|
||||
|
102
net/lwip/wget.c
102
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;
|
||||
|
||||
|
Reference in New Issue
Block a user