Merge patch series "Enable https for wget"

Ilias Apalodimas <ilias.apalodimas@linaro.org> says:

Hi all,

This is a respin of [1] adding https support to wget. In short

patch#1 enables the crypto algorithms we need in mbedTLS
patches#2, #3 enable anf fix the lwIP part we need
patch#4 is adding https:// parsing support in our wget
patch#5 is making https:// the default for QEMU lwip defconfig so
people can easily test
and finaly patch#6 updates our documentation

[1] https://lore.kernel.org/u-boot/20241024112449.1362319-1-ilias.apalodimas@linaro.org/

Link: https://lore.kernel.org/r/20241110083017.367565-1-ilias.apalodimas@linaro.org
This commit is contained in:
Tom Rini 2024-11-12 19:10:01 -06:00
commit b30787ad24
13 changed files with 278 additions and 40 deletions

View file

@ -2124,6 +2124,25 @@ config CMD_WGET
wget is a simple command to download kernel, or other files, wget is a simple command to download kernel, or other files,
from a http server over TCP. from a http server over TCP.
config WGET_HTTPS
bool "wget https"
depends on CMD_WGET
depends on PROT_TCP_LWIP
depends on MBEDTLS_LIB
select SHA256
select RSA
select ASYMMETRIC_KEY_TYPE
select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
select X509_CERTIFICATE_PARSER
select PKCS7_MESSAGE_PARSER
select MBEDTLS_LIB_CRYPTO
select MBEDTLS_LIB_TLS
select RSA_VERIFY_WITH_PKEY
select X509_CERTIFICATE_PARSER
select PKCS7_MESSAGE_PARSER
help
Enable TLS over http for wget.
endif # if CMD_NET endif # if CMD_NET
config CMD_PXE config CMD_PXE

View file

@ -7,3 +7,4 @@ CONFIG_NET_LWIP=y
CONFIG_CMD_DNS=y CONFIG_CMD_DNS=y
CONFIG_CMD_WGET=y CONFIG_CMD_WGET=y
CONFIG_EFI_HTTP_BOOT=y CONFIG_EFI_HTTP_BOOT=y
CONFIG_WGET_HTTPS=y

View file

@ -681,8 +681,8 @@ UEFI variables. Booting according to these variables is possible via::
As of U-Boot v2020.10 UEFI variables cannot be set at runtime. The U-Boot As of U-Boot v2020.10 UEFI variables cannot be set at runtime. The U-Boot
command 'efidebug' can be used to set the variables. command 'efidebug' can be used to set the variables.
UEFI HTTP Boot UEFI HTTP Boot using the legacy TCP stack
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
HTTP Boot provides the capability for system deployment and configuration HTTP Boot provides the capability for system deployment and configuration
over the network. HTTP Boot can be activated by specifying:: over the network. HTTP Boot can be activated by specifying::
@ -715,6 +715,47 @@ We need to preset the "httpserverip" environment variable to proceed the wget::
setenv httpserverip 192.168.1.1 setenv httpserverip 192.168.1.1
UEFI HTTP(s) Boot using lwIP
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Similar to the above U-Boot can do EFI HTTP boot using lwIP. If we combine this
with Mbed TLS we can also download from https://
HTTP(s) Boot can be activated by specifying::
CONFIG_EFI_HTTP_BOOT
CONFIG_NET_LWIP
CONFIG_WGET_HTTPS
For QEMU targets there's a Kconfig that supports this by default::
make qemu_arm64_lwip_defconfig
The commands and functionality are similar to the legacy stack, with the notable
exception of not having to define an "httpserverip" if you are trying to resolve
an IP. However, lwIP code doesn't yet support redirects::
=> efidebug boot add -u 1 netinst https://cdimage.debian.org/cdimage/weekly-builds/arm64/iso-cd/debian-testing-arm64-netinst.iso
=> dhcp
DHCP client bound to address 10.0.2.15 (3 ms)
=> efidebug boot order 1
=> bootefi bootmgr
HTTP server error 302
Loading Boot0001 'netinst' failed
EFI boot manager: Cannot load any image
If the url you specified isn't a redirect::
=> efidebug boot add -u 1 netinst https://download.rockylinux.org/pub/rocky/9/isos/aarch64/Rocky-9.4-aarch64-minimal.iso
=> dhcp
=> bootefi bootmgr
#######################################
If the downloaded file extension is .iso or .img file, efibootmgr tries to
mount the image and boot with the default file(e.g. EFI/BOOT/BOOTAA64.EFI).
If the downloaded file is PE-COFF image, load the downloaded file and
start it.
Executing the built in hello world application Executing the built in hello world application
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View file

@ -53,3 +53,6 @@ obj-y += \
lwip/src/core/timeouts.o \ lwip/src/core/timeouts.o \
lwip/src/core/udp.o \ lwip/src/core/udp.o \
lwip/src/netif/ethernet.o lwip/src/netif/ethernet.o
obj-$(CONFIG_MBEDTLS_LIB_TLS) += lwip/src/apps/altcp_tls/altcp_tls_mbedtls.o \
lwip/src/apps/altcp_tls/altcp_tls_mbedtls_mem.o

View file

@ -70,7 +70,6 @@
/* @todo: which includes are really needed? */ /* @todo: which includes are really needed? */
#include "mbedtls/entropy.h" #include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h" #include "mbedtls/ctr_drbg.h"
#include "mbedtls/certs.h"
#include "mbedtls/x509.h" #include "mbedtls/x509.h"
#include "mbedtls/ssl.h" #include "mbedtls/ssl.h"
#include "mbedtls/net_sockets.h" #include "mbedtls/net_sockets.h"
@ -81,8 +80,6 @@
#include "mbedtls/ssl_cache.h" #include "mbedtls/ssl_cache.h"
#include "mbedtls/ssl_ticket.h" #include "mbedtls/ssl_ticket.h"
#include "mbedtls/ssl_internal.h" /* to call mbedtls_flush_output after ERR_MEM */
#include <string.h> #include <string.h>
#ifndef ALTCP_MBEDTLS_ENTROPY_PTR #ifndef ALTCP_MBEDTLS_ENTROPY_PTR
@ -109,6 +106,7 @@ struct altcp_tls_config {
u8_t pkey_count; u8_t pkey_count;
u8_t pkey_max; u8_t pkey_max;
mbedtls_x509_crt *ca; mbedtls_x509_crt *ca;
char host[256];
#if defined(MBEDTLS_SSL_CACHE_C) && ALTCP_MBEDTLS_USE_SESSION_CACHE #if defined(MBEDTLS_SSL_CACHE_C) && ALTCP_MBEDTLS_USE_SESSION_CACHE
/** Inter-connection cache for fast connection startup */ /** Inter-connection cache for fast connection startup */
struct mbedtls_ssl_cache_context cache; struct mbedtls_ssl_cache_context cache;
@ -132,6 +130,16 @@ static err_t altcp_mbedtls_lower_recv_process(struct altcp_pcb *conn, altcp_mbed
static err_t altcp_mbedtls_handle_rx_appldata(struct altcp_pcb *conn, altcp_mbedtls_state_t *state); static err_t altcp_mbedtls_handle_rx_appldata(struct altcp_pcb *conn, altcp_mbedtls_state_t *state);
static int altcp_mbedtls_bio_send(void *ctx, const unsigned char *dataptr, size_t size); static int altcp_mbedtls_bio_send(void *ctx, const unsigned char *dataptr, size_t size);
static void
altcp_mbedtls_flush_output(altcp_mbedtls_state_t *state)
{
if (state->ssl_context.MBEDTLS_PRIVATE(out_left) != 0) {
int flushed = mbedtls_ssl_send_alert_message(&state->ssl_context, 0, 0);
if (flushed) {
LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_send_alert_message failed: %d\n", flushed));
}
}
}
/* callback functions from inner/lower connection: */ /* callback functions from inner/lower connection: */
@ -524,14 +532,14 @@ altcp_mbedtls_lower_sent(void *arg, struct altcp_pcb *inner_conn, u16_t len)
LWIP_ASSERT("state", state != NULL); LWIP_ASSERT("state", state != NULL);
LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn); LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn);
/* calculate TLS overhead part to not send it to application */ /* calculate TLS overhead part to not send it to application */
overhead = state->overhead_bytes_adjust + state->ssl_context.out_left; overhead = state->overhead_bytes_adjust + state->ssl_context.MBEDTLS_PRIVATE(out_left);
if ((unsigned)overhead > len) { if ((unsigned)overhead > len) {
overhead = len; overhead = len;
} }
/* remove ACKed bytes from overhead adjust counter */ /* remove ACKed bytes from overhead adjust counter */
state->overhead_bytes_adjust -= len; state->overhead_bytes_adjust -= len;
/* try to send more if we failed before (may increase overhead adjust counter) */ /* try to send more if we failed before (may increase overhead adjust counter) */
mbedtls_ssl_flush_output(&state->ssl_context); altcp_mbedtls_flush_output(state);
/* remove calculated overhead from ACKed bytes len */ /* remove calculated overhead from ACKed bytes len */
app_len = len - (u16_t)overhead; app_len = len - (u16_t)overhead;
/* update application write counter and inform application */ /* update application write counter and inform application */
@ -559,7 +567,7 @@ altcp_mbedtls_lower_poll(void *arg, struct altcp_pcb *inner_conn)
if (conn->state) { if (conn->state) {
altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state; altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state;
/* try to send more if we failed before */ /* try to send more if we failed before */
mbedtls_ssl_flush_output(&state->ssl_context); altcp_mbedtls_flush_output(state);
if (altcp_mbedtls_handle_rx_appldata(conn, state) == ERR_ABRT) { if (altcp_mbedtls_handle_rx_appldata(conn, state) == ERR_ABRT) {
return ERR_ABRT; return ERR_ABRT;
} }
@ -635,6 +643,7 @@ altcp_mbedtls_setup(void *conf, struct altcp_pcb *conn, struct altcp_pcb *inner_
/* tell mbedtls about our I/O functions */ /* tell mbedtls about our I/O functions */
mbedtls_ssl_set_bio(&state->ssl_context, conn, altcp_mbedtls_bio_send, altcp_mbedtls_bio_recv, NULL); mbedtls_ssl_set_bio(&state->ssl_context, conn, altcp_mbedtls_bio_send, altcp_mbedtls_bio_recv, NULL);
mbedtls_ssl_set_hostname(&state->ssl_context, config->host);
altcp_mbedtls_setup_callbacks(conn, inner_conn); altcp_mbedtls_setup_callbacks(conn, inner_conn);
conn->inner_conn = inner_conn; conn->inner_conn = inner_conn;
conn->fns = &altcp_mbedtls_functions; conn->fns = &altcp_mbedtls_functions;
@ -683,7 +692,7 @@ altcp_tls_set_session(struct altcp_pcb *conn, struct altcp_tls_session *session)
if (session && conn && conn->state) { if (session && conn && conn->state) {
altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state; altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state;
int ret = -1; int ret = -1;
if (session->data.start) if (session->data.MBEDTLS_PRIVATE(start))
ret = mbedtls_ssl_set_session(&state->ssl_context, &session->data); ret = mbedtls_ssl_set_session(&state->ssl_context, &session->data);
return ret < 0 ? ERR_VAL : ERR_OK; return ret < 0 ? ERR_VAL : ERR_OK;
} }
@ -776,7 +785,7 @@ altcp_tls_create_config(int is_server, u8_t cert_count, u8_t pkey_count, int hav
struct altcp_tls_config *conf; struct altcp_tls_config *conf;
mbedtls_x509_crt *mem; mbedtls_x509_crt *mem;
if (TCP_WND < MBEDTLS_SSL_MAX_CONTENT_LEN) { if (TCP_WND < MBEDTLS_SSL_IN_CONTENT_LEN || TCP_WND < MBEDTLS_SSL_OUT_CONTENT_LEN) {
LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG|LWIP_DBG_LEVEL_SERIOUS, LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG|LWIP_DBG_LEVEL_SERIOUS,
("altcp_tls: TCP_WND is smaller than the RX decrypion buffer, connection RX might stall!\n")); ("altcp_tls: TCP_WND is smaller than the RX decrypion buffer, connection RX might stall!\n"));
} }
@ -900,7 +909,7 @@ err_t altcp_tls_config_server_add_privkey_cert(struct altcp_tls_config *config,
return ERR_VAL; return ERR_VAL;
} }
ret = mbedtls_pk_parse_key(pkey, (const unsigned char *) privkey, privkey_len, privkey_pass, privkey_pass_len); ret = mbedtls_pk_parse_key(pkey, (const unsigned char *) privkey, privkey_len, privkey_pass, privkey_pass_len, mbedtls_ctr_drbg_random, &altcp_tls_entropy_rng->ctr_drbg);
if (ret != 0) { if (ret != 0) {
LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_pk_parse_public_key failed: %d\n", ret)); LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_pk_parse_public_key failed: %d\n", ret));
mbedtls_x509_crt_free(srvcert); mbedtls_x509_crt_free(srvcert);
@ -944,7 +953,7 @@ altcp_tls_create_config_server_privkey_cert(const u8_t *privkey, size_t privkey_
} }
static struct altcp_tls_config * static struct altcp_tls_config *
altcp_tls_create_config_client_common(const u8_t *ca, size_t ca_len, int is_2wayauth) altcp_tls_create_config_client_common(const u8_t *ca, size_t ca_len, int is_2wayauth, char *host)
{ {
int ret; int ret;
struct altcp_tls_config *conf = altcp_tls_create_config(0, (is_2wayauth) ? 1 : 0, (is_2wayauth) ? 1 : 0, ca != NULL); struct altcp_tls_config *conf = altcp_tls_create_config(0, (is_2wayauth) ? 1 : 0, (is_2wayauth) ? 1 : 0, ca != NULL);
@ -966,13 +975,15 @@ altcp_tls_create_config_client_common(const u8_t *ca, size_t ca_len, int is_2way
mbedtls_ssl_conf_ca_chain(&conf->conf, conf->ca, NULL); mbedtls_ssl_conf_ca_chain(&conf->conf, conf->ca, NULL);
} }
strlcpy(conf->host, host, sizeof(conf->host));
return conf; return conf;
} }
struct altcp_tls_config * struct altcp_tls_config *
altcp_tls_create_config_client(const u8_t *ca, size_t ca_len) altcp_tls_create_config_client(const u8_t *ca, size_t ca_len, char *host)
{ {
return altcp_tls_create_config_client_common(ca, ca_len, 0); return altcp_tls_create_config_client_common(ca, ca_len, 0, host);
} }
struct altcp_tls_config * struct altcp_tls_config *
@ -988,7 +999,7 @@ altcp_tls_create_config_client_2wayauth(const u8_t *ca, size_t ca_len, const u8_
return NULL; return NULL;
} }
conf = altcp_tls_create_config_client_common(ca, ca_len, 1); conf = altcp_tls_create_config_client_common(ca, ca_len, 1, NULL);
if (conf == NULL) { if (conf == NULL) {
return NULL; return NULL;
} }
@ -1003,7 +1014,7 @@ altcp_tls_create_config_client_2wayauth(const u8_t *ca, size_t ca_len, const u8_
} }
mbedtls_pk_init(conf->pkey); mbedtls_pk_init(conf->pkey);
ret = mbedtls_pk_parse_key(conf->pkey, privkey, privkey_len, privkey_pass, privkey_pass_len); ret = mbedtls_pk_parse_key(conf->pkey, privkey, privkey_len, privkey_pass, privkey_pass_len, mbedtls_ctr_drbg_random, &altcp_tls_entropy_rng->ctr_drbg);
if (ret != 0) { if (ret != 0) {
LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_pk_parse_key failed: %d 0x%x\n", ret, -1*ret)); LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_pk_parse_key failed: %d 0x%x\n", ret, -1*ret));
altcp_tls_free_config(conf); altcp_tls_free_config(conf);
@ -1189,7 +1200,7 @@ altcp_mbedtls_sndbuf(struct altcp_pcb *conn)
size_t ret; size_t ret;
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
/* @todo: adjust ssl_added to real value related to negotiated cipher */ /* @todo: adjust ssl_added to real value related to negotiated cipher */
size_t max_frag_len = mbedtls_ssl_get_max_frag_len(&state->ssl_context); size_t max_frag_len = mbedtls_ssl_get_max_in_record_payload(&state->ssl_context);
max_len = LWIP_MIN(max_frag_len, max_len); max_len = LWIP_MIN(max_frag_len, max_len);
#endif #endif
/* Adjust sndbuf of inner_conn with what added by SSL */ /* Adjust sndbuf of inner_conn with what added by SSL */
@ -1232,9 +1243,9 @@ altcp_mbedtls_write(struct altcp_pcb *conn, const void *dataptr, u16_t len, u8_t
/* HACK: if there is something left to send, try to flush it and only /* HACK: if there is something left to send, try to flush it and only
allow sending more if this succeeded (this is a hack because neither allow sending more if this succeeded (this is a hack because neither
returning 0 nor MBEDTLS_ERR_SSL_WANT_WRITE worked for me) */ returning 0 nor MBEDTLS_ERR_SSL_WANT_WRITE worked for me) */
if (state->ssl_context.out_left) { if (state->ssl_context.MBEDTLS_PRIVATE(out_left)) {
mbedtls_ssl_flush_output(&state->ssl_context); altcp_mbedtls_flush_output(state);
if (state->ssl_context.out_left) { if (state->ssl_context.MBEDTLS_PRIVATE(out_left)) {
return ERR_MEM; return ERR_MEM;
} }
} }
@ -1284,6 +1295,8 @@ altcp_mbedtls_bio_send(void *ctx, const unsigned char *dataptr, size_t size)
while (size_left) { while (size_left) {
u16_t write_len = (u16_t)LWIP_MIN(size_left, 0xFFFF); u16_t write_len = (u16_t)LWIP_MIN(size_left, 0xFFFF);
err_t err = altcp_write(conn->inner_conn, (const void *)dataptr, write_len, apiflags); err_t err = altcp_write(conn->inner_conn, (const void *)dataptr, write_len, apiflags);
/* try to send data... */
altcp_output(conn->inner_conn);
if (err == ERR_OK) { if (err == ERR_OK) {
written += write_len; written += write_len;
size_left -= write_len; size_left -= write_len;

View file

@ -1255,14 +1255,6 @@ tcp_output(struct tcp_pcb *pcb)
LWIP_ASSERT("don't call tcp_output for listen-pcbs", LWIP_ASSERT("don't call tcp_output for listen-pcbs",
pcb->state != LISTEN); pcb->state != LISTEN);
/* First, check if we are invoked by the TCP input processing
code. If so, we do not output anything. Instead, we rely on the
input processing code to call us when input processing is done
with. */
if (tcp_input_pcb == pcb) {
return ERR_OK;
}
wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd); wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
seg = pcb->unsent; seg = pcb->unsent;

View file

@ -92,7 +92,7 @@ struct altcp_tls_config *altcp_tls_create_config_server_privkey_cert(const u8_t
/** @ingroup altcp_tls /** @ingroup altcp_tls
* Create an ALTCP_TLS client configuration handle * Create an ALTCP_TLS client configuration handle
*/ */
struct altcp_tls_config *altcp_tls_create_config_client(const u8_t *cert, size_t cert_len); struct altcp_tls_config *altcp_tls_create_config_client(const u8_t *cert, size_t cert_len, char *host);
/** @ingroup altcp_tls /** @ingroup altcp_tls
* Create an ALTCP_TLS client configuration handle with two-way server/client authentication * Create an ALTCP_TLS client configuration handle with two-way server/client authentication

View file

@ -154,4 +154,10 @@
#define MEMP_MEM_INIT 1 #define MEMP_MEM_INIT 1
#define MEM_LIBC_MALLOC 1 #define MEM_LIBC_MALLOC 1
#if defined(CONFIG_MBEDTLS_LIB_TLS)
#define LWIP_ALTCP 1
#define LWIP_ALTCP_TLS 1
#define LWIP_ALTCP_TLS_MBEDTLS 1
#endif
#endif /* LWIP_UBOOT_LWIPOPTS_H */ #endif /* LWIP_UBOOT_LWIPOPTS_H */

View file

@ -430,4 +430,16 @@ endif # SPL
endif # MBEDTLS_LIB_X509 endif # MBEDTLS_LIB_X509
config MBEDTLS_LIB_TLS
bool "MbedTLS TLS library"
depends on RSA_PUBLIC_KEY_PARSER_MBEDTLS
depends on X509_CERTIFICATE_PARSER_MBEDTLS
depends on ASYMMETRIC_PUBLIC_KEY_MBEDTLS
depends on ASN1_DECODER_MBEDTLS
depends on ASYMMETRIC_PUBLIC_KEY_MBEDTLS
depends on MBEDTLS_LIB_CRYPTO
help
Enable MbedTLS TLS library. Required for HTTPs support
in wget
endif # MBEDTLS_LIB endif # MBEDTLS_LIB

View file

@ -26,6 +26,7 @@ mbedtls_lib_crypto-y := \
$(MBEDTLS_LIB_DIR)/platform_util.o \ $(MBEDTLS_LIB_DIR)/platform_util.o \
$(MBEDTLS_LIB_DIR)/constant_time.o \ $(MBEDTLS_LIB_DIR)/constant_time.o \
$(MBEDTLS_LIB_DIR)/md.o $(MBEDTLS_LIB_DIR)/md.o
mbedtls_lib_crypto-$(CONFIG_$(SPL_)MD5_MBEDTLS) += $(MBEDTLS_LIB_DIR)/md5.o mbedtls_lib_crypto-$(CONFIG_$(SPL_)MD5_MBEDTLS) += $(MBEDTLS_LIB_DIR)/md5.o
mbedtls_lib_crypto-$(CONFIG_$(SPL_)SHA1_MBEDTLS) += $(MBEDTLS_LIB_DIR)/sha1.o mbedtls_lib_crypto-$(CONFIG_$(SPL_)SHA1_MBEDTLS) += $(MBEDTLS_LIB_DIR)/sha1.o
mbedtls_lib_crypto-$(CONFIG_$(SPL_)SHA256_MBEDTLS) += \ mbedtls_lib_crypto-$(CONFIG_$(SPL_)SHA256_MBEDTLS) += \
@ -54,3 +55,33 @@ mbedtls_lib_x509-$(CONFIG_$(SPL_)X509_CERTIFICATE_PARSER_MBEDTLS) += \
$(MBEDTLS_LIB_DIR)/x509_crt.o $(MBEDTLS_LIB_DIR)/x509_crt.o
mbedtls_lib_x509-$(CONFIG_$(SPL_)PKCS7_MESSAGE_PARSER_MBEDTLS) += \ mbedtls_lib_x509-$(CONFIG_$(SPL_)PKCS7_MESSAGE_PARSER_MBEDTLS) += \
$(MBEDTLS_LIB_DIR)/pkcs7.o $(MBEDTLS_LIB_DIR)/pkcs7.o
#mbedTLS TLS support
obj-$(CONFIG_MBEDTLS_LIB_TLS) += mbedtls_lib_tls.o
mbedtls_lib_tls-y := \
$(MBEDTLS_LIB_DIR)/mps_reader.o \
$(MBEDTLS_LIB_DIR)/mps_trace.o \
$(MBEDTLS_LIB_DIR)/net_sockets.o \
$(MBEDTLS_LIB_DIR)/pk_ecc.o \
$(MBEDTLS_LIB_DIR)/ssl_cache.o \
$(MBEDTLS_LIB_DIR)/ssl_ciphersuites.o \
$(MBEDTLS_LIB_DIR)/ssl_client.o \
$(MBEDTLS_LIB_DIR)/ssl_cookie.o \
$(MBEDTLS_LIB_DIR)/ssl_debug_helpers_generated.o \
$(MBEDTLS_LIB_DIR)/ssl_msg.o \
$(MBEDTLS_LIB_DIR)/ssl_ticket.o \
$(MBEDTLS_LIB_DIR)/ssl_tls.o \
$(MBEDTLS_LIB_DIR)/ssl_tls12_client.o \
$(MBEDTLS_LIB_DIR)/hmac_drbg.o \
$(MBEDTLS_LIB_DIR)/ctr_drbg.o \
$(MBEDTLS_LIB_DIR)/entropy.o \
$(MBEDTLS_LIB_DIR)/entropy_poll.o \
$(MBEDTLS_LIB_DIR)/aes.o \
$(MBEDTLS_LIB_DIR)/cipher.o \
$(MBEDTLS_LIB_DIR)/cipher_wrap.o \
$(MBEDTLS_LIB_DIR)/ecdh.o \
$(MBEDTLS_LIB_DIR)/ecdsa.o \
$(MBEDTLS_LIB_DIR)/ecp.o \
$(MBEDTLS_LIB_DIR)/ecp_curves.o \
$(MBEDTLS_LIB_DIR)/ecp_curves_new.o \
$(MBEDTLS_LIB_DIR)/gcm.o \

View file

@ -87,4 +87,56 @@
#endif /* #if defined CONFIG_MBEDTLS_LIB_X509 */ #endif /* #if defined CONFIG_MBEDTLS_LIB_X509 */
#if IS_ENABLED(CONFIG_MBEDTLS_LIB_TLS)
#include "rtc.h"
/* Generic options */
#define MBEDTLS_ENTROPY_HARDWARE_ALT
#define MBEDTLS_HAVE_TIME
#define MBEDTLS_PLATFORM_MS_TIME_ALT
#define MBEDTLS_PLATFORM_TIME_MACRO rtc_mktime
#define MBEDTLS_PLATFORM_C
#define MBEDTLS_SSL_CLI_C
#define MBEDTLS_SSL_TLS_C
#define MBEDTLS_CIPHER_C
#define MBEDTLS_MD_C
#define MBEDTLS_CTR_DRBG_C
#define MBEDTLS_AES_C
#define MBEDTLS_ENTROPY_C
#define MBEDTLS_NO_PLATFORM_ENTROPY
#define MBEDTLS_SSL_PROTO_TLS1_2
#define MBEDTLS_SSL_SERVER_NAME_INDICATION
#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
/* RSA */
#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
#define MBEDTLS_GCM_C
/* ECDSA */
#define MBEDTLS_ECDSA_C
#define MBEDTLS_ECDH_C
#define MBEDTLS_ECDSA_DETERMINISTIC
#define MBEDTLS_HMAC_DRBG_C
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
#define MBEDTLS_CAN_ECDH
#define MBEDTLS_PK_CAN_ECDSA_SIGN
#define MBEDTLS_ECP_C
#define MBEDTLS_ECP_DP_SECP256K1_ENABLED
#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
#define MBEDTLS_ECP_DP_SECP224R1_ENABLED
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
#define MBEDTLS_ECP_DP_SECP521R1_ENABLED
#define MBEDTLS_ECP_DP_SECP192K1_ENABLED
#define MBEDTLS_ECP_DP_SECP224K1_ENABLED
#define MBEDTLS_ECP_DP_SECP256K1_ENABLED
#define MBEDTLS_ECP_DP_BP256R1_ENABLED
#define MBEDTLS_ECP_DP_BP384R1_ENABLED
#define MBEDTLS_ECP_DP_BP512R1_ENABLED
#endif /* #if defined CONFIG_MBEDTLS_LIB_TLS */
#endif /* #if defined CONFIG_MBEDTLS_LIB */ #endif /* #if defined CONFIG_MBEDTLS_LIB */

View file

@ -37,7 +37,7 @@ config PROT_UDP_LWIP
config LWIP_TCP_WND config LWIP_TCP_WND
int "Value of TCP_WND" int "Value of TCP_WND"
default 8000 if ARCH_QEMU default 32768 if ARCH_QEMU
default 3000000 default 3000000
help help
Default value for TCP_WND in the lwIP configuration Default value for TCP_WND in the lwIP configuration

View file

@ -7,13 +7,17 @@
#include <efi_loader.h> #include <efi_loader.h>
#include <image.h> #include <image.h>
#include <lwip/apps/http_client.h> #include <lwip/apps/http_client.h>
#include "lwip/altcp_tls.h"
#include <lwip/timeouts.h> #include <lwip/timeouts.h>
#include <rng.h>
#include <mapmem.h> #include <mapmem.h>
#include <net.h> #include <net.h>
#include <time.h> #include <time.h>
#include <dm/uclass.h>
#define SERVER_NAME_SIZE 200 #define SERVER_NAME_SIZE 200
#define HTTP_PORT_DEFAULT 80 #define HTTP_PORT_DEFAULT 80
#define HTTPS_PORT_DEFAULT 443
#define PROGRESS_PRINT_STEP_BYTES (100 * 1024) #define PROGRESS_PRINT_STEP_BYTES (100 * 1024)
enum done_state { enum done_state {
@ -32,18 +36,56 @@ struct wget_ctx {
enum done_state done; enum done_state done;
}; };
static int parse_url(char *url, char *host, u16 *port, char **path) bool wget_validate_uri(char *uri);
int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len,
size_t *olen)
{
struct udevice *dev;
u64 rng = 0;
int ret;
*olen = 0;
ret = uclass_get_device(UCLASS_RNG, 0, &dev);
if (ret) {
log_err("Failed to get an rng: %d\n", ret);
return ret;
}
ret = dm_rng_read(dev, &rng, sizeof(rng));
if (ret)
return ret;
memcpy(output, &rng, len);
*olen = sizeof(rng);
return 0;
}
static int parse_url(char *url, char *host, u16 *port, char **path,
bool *is_https)
{ {
char *p, *pp; char *p, *pp;
long lport; long lport;
size_t prefix_len = 0;
p = strstr(url, "http://"); if (!wget_validate_uri(url)) {
if (!p) { log_err("Invalid URL. Use http(s)://\n");
log_err("only http:// is supported\n");
return -EINVAL; return -EINVAL;
} }
p += strlen("http://"); *is_https = false;
*port = HTTP_PORT_DEFAULT;
prefix_len = strlen("http://");
p = strstr(url, "http://");
if (!p) {
p = strstr(url, "https://");
prefix_len = strlen("https://");
*port = HTTPS_PORT_DEFAULT;
*is_https = true;
}
p += prefix_len;
/* Parse hostname */ /* Parse hostname */
pp = strchr(p, ':'); pp = strchr(p, ':');
@ -67,9 +109,8 @@ static int parse_url(char *url, char *host, u16 *port, char **path)
if (lport > 65535) if (lport > 65535)
return -EINVAL; return -EINVAL;
*port = (u16)lport; *port = (u16)lport;
} else {
*port = HTTP_PORT_DEFAULT;
} }
if (*pp != '/') if (*pp != '/')
return -EINVAL; return -EINVAL;
*path = pp; *path = pp;
@ -210,12 +251,16 @@ static void httpc_result_cb(void *arg, httpc_result_t httpc_result,
static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri) static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri)
{ {
char server_name[SERVER_NAME_SIZE]; char server_name[SERVER_NAME_SIZE];
#if defined CONFIG_WGET_HTTPS
altcp_allocator_t tls_allocator;
#endif
httpc_connection_t conn; httpc_connection_t conn;
httpc_state_t *state; httpc_state_t *state;
struct netif *netif; struct netif *netif;
struct wget_ctx ctx; struct wget_ctx ctx;
char *path; char *path;
u16 port; u16 port;
bool is_https;
ctx.daddr = dst_addr; ctx.daddr = dst_addr;
ctx.saved_daddr = dst_addr; ctx.saved_daddr = dst_addr;
@ -224,7 +269,7 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri)
ctx.prevsize = 0; ctx.prevsize = 0;
ctx.start_time = 0; ctx.start_time = 0;
if (parse_url(uri, server_name, &port, &path)) if (parse_url(uri, server_name, &port, &path, &is_https))
return CMD_RET_USAGE; return CMD_RET_USAGE;
netif = net_lwip_new_netif(udev); netif = net_lwip_new_netif(udev);
@ -232,6 +277,22 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri)
return -1; return -1;
memset(&conn, 0, sizeof(conn)); memset(&conn, 0, sizeof(conn));
#if defined CONFIG_WGET_HTTPS
if (is_https) {
tls_allocator.alloc = &altcp_tls_alloc;
tls_allocator.arg =
altcp_tls_create_config_client(NULL, 0, server_name);
if (!tls_allocator.arg) {
log_err("error: Cannot create a TLS connection\n");
net_lwip_remove_netif(netif);
return -1;
}
conn.altcp_allocator = &tls_allocator;
}
#endif
conn.result_fn = httpc_result_cb; conn.result_fn = httpc_result_cb;
ctx.path = path; ctx.path = path;
if (httpc_get_file_dns(server_name, port, path, &conn, httpc_recv_cb, if (httpc_get_file_dns(server_name, port, path, &conn, httpc_recv_cb,
@ -316,6 +377,7 @@ bool wget_validate_uri(char *uri)
char c; char c;
bool ret = true; bool ret = true;
char *str_copy, *s, *authority; char *str_copy, *s, *authority;
size_t prefix_len = 0;
for (c = 0x1; c < 0x21; c++) { for (c = 0x1; c < 0x21; c++) {
if (strchr(uri, c)) { if (strchr(uri, c)) {
@ -323,15 +385,21 @@ bool wget_validate_uri(char *uri)
return false; return false;
} }
} }
if (strchr(uri, 0x7f)) { if (strchr(uri, 0x7f)) {
log_err("invalid character is used\n"); log_err("invalid character is used\n");
return false; return false;
} }
if (strncmp(uri, "http://", 7)) { if (!strncmp(uri, "http://", strlen("http://"))) {
log_err("only http:// is supported\n"); prefix_len = strlen("http://");
} else if (!strncmp(uri, "https://", strlen("https://"))) {
prefix_len = strlen("https://");
} else {
log_err("only http(s):// is supported\n");
return false; return false;
} }
str_copy = strdup(uri); str_copy = strdup(uri);
if (!str_copy) if (!str_copy)
return false; return false;