From 052b40680dd400c4239c901f49c0d5bc5e6d1f5d Mon Sep 17 00:00:00 2001 From: cpq Date: Sun, 29 Jan 2023 22:39:01 +0000 Subject: [PATCH] Add TLS to pico-w5500 baremetal example --- examples/device-dashboard/main.c | 2 +- examples/device-dashboard/net.c | 27 ++++++- examples/esp32/device-dashboard/main/main.c | 2 +- examples/mip-tap/main.c | 2 +- examples/rp2040/pico-rndis-dashboard/main.c | 2 +- examples/rp2040/pico-w5500/CMakeLists.txt | 11 ++- examples/rp2040/pico-w5500/Makefile | 9 ++- examples/rp2040/pico-w5500/main.c | 3 +- examples/rp2040/pico-w5500/tlsconf.h | 81 +++++++++++++++++++ examples/stm32/nucleo-f429zi-baremetal/main.c | 2 +- examples/stm32/nucleo-f746zg-baremetal/main.c | 2 +- examples/ti/ek-tm4c1294xl-baremetal/main.c | 2 +- examples/zephyr/device-dashboard/src/main.c | 2 +- mip/mip.c | 11 ++- mongoose.c | 16 +++- 15 files changed, 152 insertions(+), 22 deletions(-) create mode 100644 examples/rp2040/pico-w5500/tlsconf.h diff --git a/examples/device-dashboard/main.c b/examples/device-dashboard/main.c index a60c6739..094b0acd 100644 --- a/examples/device-dashboard/main.c +++ b/examples/device-dashboard/main.c @@ -10,7 +10,7 @@ int main(void) { struct mg_mgr mgr; mg_log_set(MG_LL_DEBUG); // Set debug log level mg_mgr_init(&mgr); - mg_http_listen(&mgr, s_listening_url, device_dashboard_fn, &mgr); + mg_http_listen(&mgr, s_listening_url, device_dashboard_fn, NULL); MG_INFO(("Listening on %s", s_listening_url)); while (mgr.conns != NULL) mg_mgr_poll(&mgr, 500); mg_mgr_free(&mgr); diff --git a/examples/device-dashboard/net.c b/examples/device-dashboard/net.c index 61f1be75..9199d198 100644 --- a/examples/device-dashboard/net.c +++ b/examples/device-dashboard/net.c @@ -9,7 +9,27 @@ #define MQTT_PUBLISH_TOPIC "mg/my_device" #define MQTT_SUBSCRIBE_TOPIC "mg/#" -static time_t s_boot_timestamp = 0; // Updated by SNTP +// Certificate generation procedure: +// openssl ecparam -name prime256v1 -genkey -noout -out key.pem +// openssl req -new -key key.pem -x509 -nodes -days 3650 -out cert.pem +static const char *s_ssl_cert = + "-----BEGIN CERTIFICATE-----\n" + "MIIBCTCBsAIJAK9wbIDkHnAoMAoGCCqGSM49BAMCMA0xCzAJBgNVBAYTAklFMB4X\n" + "DTIzMDEyOTIxMjEzOFoXDTMzMDEyNjIxMjEzOFowDTELMAkGA1UEBhMCSUUwWTAT\n" + "BgcqhkjOPQIBBggqhkjOPQMBBwNCAARzSQS5OHd17lUeNI+6kp9WYu0cxuEIi/JT\n" + "jphbCmdJD1cUvhmzM9/phvJT9ka10Z9toZhgnBq0o0xfTQ4jC1vwMAoGCCqGSM49\n" + "BAMCA0gAMEUCIQCe0T2E0GOiVe9KwvIEPeX1J1J0T7TNacgR0Ya33HV9VgIgNvdn\n" + "aEWiBp1xshs4iz6WbpxrS1IHucrqkZuJLfNZGZI=\n" + "-----END CERTIFICATE-----\n"; + +static const char *s_ssl_key = + "-----BEGIN EC PRIVATE KEY-----\n" + "MHcCAQEEICBz3HOkQLPBDtdknqC7k1PNsWj6HfhyNB5MenfjmqiooAoGCCqGSM49\n" + "AwEHoUQDQgAEc0kEuTh3de5VHjSPupKfVmLtHMbhCIvyU46YWwpnSQ9XFL4ZszPf\n" + "6YbyU/ZGtdGfbaGYYJwatKNMX00OIwtb8A==\n" + "-----END EC PRIVATE KEY-----\n"; + +static time_t s_boot_timestamp = 0; // Updated by SNTP #ifndef DISABLE_ROUTING static struct mg_connection *s_sntp_conn = NULL; // SNTP connection #endif @@ -173,6 +193,9 @@ void device_dashboard_fn(struct mg_connection *c, int ev, void *ev_data, s_config.url = strdup(MQTT_SERVER); s_config.pub = strdup(MQTT_PUBLISH_TOPIC); s_config.sub = strdup(MQTT_SUBSCRIBE_TOPIC); + } else if (ev == MG_EV_ACCEPT && fn_data != NULL) { + struct mg_tls_opts opts = {.cert = s_ssl_cert, .certkey = s_ssl_key}; + mg_tls_init(c, &opts); } else if (ev == MG_EV_HTTP_MSG) { struct mg_http_message *hm = (struct mg_http_message *) ev_data; struct user *u = getuser(hm); @@ -203,7 +226,7 @@ void device_dashboard_fn(struct mg_connection *c, int ev, void *ev_data, update_config(&hm->body, "pub", &s_config.pub); update_config(&hm->body, "sub", &s_config.sub); if (s_mqtt) s_mqtt->is_closing = 1; // Ask to disconnect from MQTT - send_notification(fn_data, "{%Q:%Q,%Q:null}", "name", "config", "data"); + send_notification(c->mgr, "{%Q:%Q,%Q:null}", "name", "config", "data"); mg_http_reply(c, 200, "", "ok\n"); } else { mg_http_reply(c, 403, "", "Denied\n"); diff --git a/examples/esp32/device-dashboard/main/main.c b/examples/esp32/device-dashboard/main/main.c index e221beb0..4762b02e 100644 --- a/examples/esp32/device-dashboard/main/main.c +++ b/examples/esp32/device-dashboard/main/main.c @@ -30,6 +30,6 @@ void app_main(void) { mg_log_set(MG_LL_DEBUG); // Set log level mg_mgr_init(&mgr); MG_INFO(("Mongoose v%s on %s", MG_VERSION, s_listening_url)); - mg_http_listen(&mgr, s_listening_url, device_dashboard_fn, &mgr); + mg_http_listen(&mgr, s_listening_url, device_dashboard_fn, NULL); for (;;) mg_mgr_poll(&mgr, 1000); // Infinite event loop } diff --git a/examples/mip-tap/main.c b/examples/mip-tap/main.c index 082ee290..2d89224a 100644 --- a/examples/mip-tap/main.c +++ b/examples/mip-tap/main.c @@ -104,7 +104,7 @@ int main(int argc, char *argv[]) { MG_INFO(("Listening on : %s", s_listening_address)); extern void device_dashboard_fn(struct mg_connection *, int, void *, void *); - mg_http_listen(&mgr, s_listening_address, device_dashboard_fn, &mgr); + mg_http_listen(&mgr, s_listening_address, device_dashboard_fn, NULL); while (s_signo == 0) mg_mgr_poll(&mgr, 100); // Infinite event loop diff --git a/examples/rp2040/pico-rndis-dashboard/main.c b/examples/rp2040/pico-rndis-dashboard/main.c index 9650040b..9695e664 100644 --- a/examples/rp2040/pico-rndis-dashboard/main.c +++ b/examples/rp2040/pico-rndis-dashboard/main.c @@ -69,7 +69,7 @@ int main(void) { MG_INFO(("Initialising application...")); extern void device_dashboard_fn(struct mg_connection *, int, void *, void *); - mg_http_listen(&mgr, "http://0.0.0.0", device_dashboard_fn, &mgr); + mg_http_listen(&mgr, "http://0.0.0.0", device_dashboard_fn, NULL); MG_INFO(("Starting event loop")); for (;;) { diff --git a/examples/rp2040/pico-w5500/CMakeLists.txt b/examples/rp2040/pico-w5500/CMakeLists.txt index 829dff0c..83a0ae9c 100644 --- a/examples/rp2040/pico-w5500/CMakeLists.txt +++ b/examples/rp2040/pico-w5500/CMakeLists.txt @@ -4,12 +4,15 @@ include(pico-sdk/pico_sdk_init.cmake) project(firmware) pico_sdk_init() +file(GLOB TLS_SOURCES "mbedtls/library/*.c") add_executable(firmware main.c ../../../mongoose.c ../../device-dashboard/net.c - ../../device-dashboard/packed_fs.c) -target_include_directories(firmware PUBLIC ../../..) + ../../device-dashboard/packed_fs.c + ${TLS_SOURCES}) + +target_include_directories(firmware PUBLIC . ../../.. mbedtls/include) target_link_libraries(firmware pico_stdlib hardware_spi) pico_add_extra_outputs(firmware) @@ -21,3 +24,7 @@ pico_enable_stdio_uart(firmware 1) add_definitions(-DMG_ENABLE_MIP=1) add_definitions(-DMG_ENABLE_PACKED_FS=1) add_definitions(-DMG_ENABLE_FILE=0) + +add_definitions(-DMG_ENABLE_MBEDTLS=1) +add_definitions(-DMBEDTLS_CONFIG_FILE=\"tlsconf.h\") +#add_definitions(-DMG_MBEDTLS_DEBUG_LEVEL=1) diff --git a/examples/rp2040/pico-w5500/Makefile b/examples/rp2040/pico-w5500/Makefile index cc341abc..2ea53476 100644 --- a/examples/rp2040/pico-w5500/Makefile +++ b/examples/rp2040/pico-w5500/Makefile @@ -1,7 +1,9 @@ SDK_VERSION ?= 1.4.0 SDK_REPO ?= https://github.com/raspberrypi/pico-sdk +MBEDTLS_VERSION ?= v2.27.0 +MBEDTLS_REPO ?= https://github.com/Mbed-TLS/mbedtls -all example build build/firmware.uf2: pico-sdk main.c +all example build build/firmware.uf2: pico-sdk mbedtls main.c test -d build || mkdir build cd build && cmake .. && make @@ -9,6 +11,9 @@ pico-sdk: git clone --depth 1 -b $(SDK_VERSION) $(SDK_REPO) $@ cd $@ && git submodule update --init +mbedtls: + git clone --depth 1 -b $(MBEDTLS_VERSION) $(MBEDTLS_REPO) $@ + # Requires env variable VCON_API_KEY set DEVICE_URL ?= https://dash.vcon.io/api/v3/devices/3 test: update @@ -20,4 +25,4 @@ update: build/firmware.uf2 curl --fail -su :$(VCON_API_KEY) $(DEVICE_URL)/ota?uf2=1 --data-binary @$< clean: - rm -rf pico-sdk build + rm -rf pico-sdk mbedtls build diff --git a/examples/rp2040/pico-w5500/main.c b/examples/rp2040/pico-w5500/main.c index 34c82763..17d2a3ab 100644 --- a/examples/rp2040/pico-w5500/main.c +++ b/examples/rp2040/pico-w5500/main.c @@ -60,7 +60,8 @@ int main(void) { MG_INFO(("Initialising application...")); extern void device_dashboard_fn(struct mg_connection *, int, void *, void *); - mg_http_listen(&mgr, "http://0.0.0.0", device_dashboard_fn, &mgr); + mg_http_listen(&mgr, "http://0.0.0.0:80", device_dashboard_fn, NULL); + mg_http_listen(&mgr, "https://0.0.0.0:443", device_dashboard_fn, ""); // SSL MG_INFO(("Starting event loop")); for (;;) { diff --git a/examples/rp2040/pico-w5500/tlsconf.h b/examples/rp2040/pico-w5500/tlsconf.h new file mode 100644 index 00000000..8ef9e365 --- /dev/null +++ b/examples/rp2040/pico-w5500/tlsconf.h @@ -0,0 +1,81 @@ +// #define MBEDTLS_HAVE_ASM +// #define MBEDTLS_HAVE_TIME + +/* mbed TLS feature support */ +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#define MBEDTLS_SSL_PROTO_TLS1_2 + +/* mbed TLS modules */ +#define MBEDTLS_AES_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_CTR_DRBG_C +#define MBEDTLS_ECDH_C +#define MBEDTLS_ECDSA_C +#define MBEDTLS_ECP_C +//#define MBEDTLS_ENTROPY_C +#define MBEDTLS_GCM_C +#define MBEDTLS_MD_C +//#define MBEDTLS_NET_C +#define MBEDTLS_OID_C +#define MBEDTLS_PK_C +#define MBEDTLS_PK_PARSE_C + +#define MBEDTLS_SHA224_C +#define MBEDTLS_SHA256_C +#define MBEDTLS_SHA384_C +#define MBEDTLS_SHA512_C +#define MBEDTLS_SSL_CLI_C +#define MBEDTLS_SSL_SRV_C +#define MBEDTLS_SSL_TLS_C +#define MBEDTLS_X509_CRT_PARSE_C +#define MBEDTLS_X509_USE_C + +/* For test certificates */ +#define MBEDTLS_BASE64_C +#define MBEDTLS_PEM_PARSE_C + +/* Save RAM at the expense of ROM */ +#define MBEDTLS_AES_ROM_TABLES + +/* Save RAM by adjusting to our exact needs */ +#define MBEDTLS_MPI_MAX_SIZE 48 // 384-bit EC curve = 48 bytes + +/* Save RAM at the expense of speed, see ecp.h */ +#define MBEDTLS_ECP_WINDOW_SIZE 2 +#define MBEDTLS_ECP_FIXED_POINT_OPTIM 0 + +/* Significant speed benefit at the expense of some ROM */ +#define MBEDTLS_ECP_NIST_OPTIM + +/* + * You should adjust this to the exact number of sources you're using: default + * is the "mbedtls_platform_entropy_poll" source, but you may want to add other + * ones. Minimum is 2 for the entropy test suite. + */ +#define MBEDTLS_ENTROPY_MAX_SOURCES 2 + +/* Save ROM and a few bytes of RAM by specifying our own ciphersuite list */ +#define MBEDTLS_SSL_CIPHERSUITES \ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, \ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + +#define MBEDTLS_SSL_IN_CONTENT_LEN 1024 +#define MBEDTLS_SSL_OUT_CONTENT_LEN 1024 + +/* These defines are present so that the config modifying scripts can enable + * them during tests/scripts/test-ref-configs.pl */ +//#define MBEDTLS_USE_PSA_CRYPTO +//#define MBEDTLS_PSA_CRYPTO_C + +/* Error messages and TLS debugging traces + * (huge code size increase, needed for tests/ssl-opt.sh) */ +//#define MBEDTLS_DEBUG_C +//#define MBEDTLS_ERROR_C + +#include +#include "mongoose.h" diff --git a/examples/stm32/nucleo-f429zi-baremetal/main.c b/examples/stm32/nucleo-f429zi-baremetal/main.c index 4ceb4f8e..ce6e8382 100644 --- a/examples/stm32/nucleo-f429zi-baremetal/main.c +++ b/examples/stm32/nucleo-f429zi-baremetal/main.c @@ -85,7 +85,7 @@ int main(void) { MG_INFO(("Initialising application...")); extern void device_dashboard_fn(struct mg_connection *, int, void *, void *); - mg_http_listen(&mgr, "http://0.0.0.0", device_dashboard_fn, &mgr); + mg_http_listen(&mgr, "http://0.0.0.0", device_dashboard_fn, NULL); MG_INFO(("Starting event loop")); for (;;) { diff --git a/examples/stm32/nucleo-f746zg-baremetal/main.c b/examples/stm32/nucleo-f746zg-baremetal/main.c index 2a0196b5..05b29a9e 100644 --- a/examples/stm32/nucleo-f746zg-baremetal/main.c +++ b/examples/stm32/nucleo-f746zg-baremetal/main.c @@ -80,7 +80,7 @@ int main(void) { MG_INFO(("Init done, starting main loop")); extern void device_dashboard_fn(struct mg_connection *, int, void *, void *); - mg_http_listen(&mgr, "http://0.0.0.0", device_dashboard_fn, &mgr); + mg_http_listen(&mgr, "http://0.0.0.0", device_dashboard_fn, NULL); for (;;) mg_mgr_poll(&mgr, 0); // Infinite event loop return 0; diff --git a/examples/ti/ek-tm4c1294xl-baremetal/main.c b/examples/ti/ek-tm4c1294xl-baremetal/main.c index bb8ff8bd..5b91e753 100644 --- a/examples/ti/ek-tm4c1294xl-baremetal/main.c +++ b/examples/ti/ek-tm4c1294xl-baremetal/main.c @@ -101,7 +101,7 @@ int main(void) { mg_timer_add(&mgr, 1000, MG_TIMER_REPEAT, blink_cb, &mif); extern void device_dashboard_fn(struct mg_connection *, int, void *, void *); - mg_http_listen(&mgr, "http://0.0.0.0", device_dashboard_fn, &mgr); + mg_http_listen(&mgr, "http://0.0.0.0", device_dashboard_fn, NULL); for (;;) mg_mgr_poll(&mgr, 0); // Infinite event loop return 0; diff --git a/examples/zephyr/device-dashboard/src/main.c b/examples/zephyr/device-dashboard/src/main.c index ec4a7f2e..8c8fbcf5 100644 --- a/examples/zephyr/device-dashboard/src/main.c +++ b/examples/zephyr/device-dashboard/src/main.c @@ -27,7 +27,7 @@ int main(int argc, char *argv[]) { mg_mgr_init(&mgr); extern void device_dashboard_fn(struct mg_connection *, int, void *, void *); - mg_http_listen(&mgr, "http://0.0.0.0:8000", device_dashboard_fn, &mgr); + mg_http_listen(&mgr, "http://0.0.0.0:8000", device_dashboard_fn, NULL); // Start infinite event loop MG_INFO(("Mongoose version : v%s", MG_VERSION)); diff --git a/mip/mip.c b/mip/mip.c index 274c143b..83fd5cd8 100644 --- a/mip/mip.c +++ b/mip/mip.c @@ -609,9 +609,14 @@ static void read_conn(struct mg_connection *c, struct pkt *pkt) { } else if (pkt->pay.len == 0) { // TODO(cpq): handle this peer's ACK } else if (seq != s->ack) { - // TODO(cpq): peer sent us SEQ which we don't expect. Retransmit rather - // than close this connection - mg_error(c, "SEQ != ACK: %x %x", seq, s->ack); + uint32_t ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len); + if (s->ack == ack) { + MG_VERBOSE(("ignoring duplicate pkt")); + } else { + // TODO(cpq): peer sent us SEQ which we don't expect. Retransmit rather + // than close this connection + mg_error(c, "SEQ != ACK: %x %x %x", seq, s->ack, ack); + } } else if (io->size - io->len < pkt->pay.len && !mg_iobuf_resize(io, io->len + pkt->pay.len)) { mg_error(c, "oom"); diff --git a/mongoose.c b/mongoose.c index 2c76e349..b6d371d8 100644 --- a/mongoose.c +++ b/mongoose.c @@ -6110,6 +6110,7 @@ static size_t mip_driver_stm32_tx(const void *buf, size_t len, struct mip_if *if s_txdesc[s_txno][0] = BIT(20) | BIT(28) | BIT(29) | BIT(30); // Chain,FS,LS s_txdesc[s_txno][0] |= BIT(31); // Set OWN bit - let DMA take over if (++s_txno >= ETH_DESC_CNT) s_txno = 0; + printf("sent\n"); } ETH->DMASR = BIT(2) | BIT(5); // Clear any prior TBUS/TUS ETH->DMATPDR = 0; // and resume @@ -6123,9 +6124,11 @@ static bool mip_driver_stm32_up(struct mip_if *ifp) { return bsr & BIT(2) ? 1 : 0; } -void ETH_IRQHandler(void); static uint32_t s_rxno; +void ETH_IRQHandler(void); void ETH_IRQHandler(void) { + static int cnt; + printf("--> %d\n", cnt++); qp_mark(QP_IRQTRIGGERED, 0); if (ETH->DMASR & BIT(6)) { // Frame received, loop ETH->DMASR = BIT(16) | BIT(6); // Clear flag @@ -7096,9 +7099,14 @@ static void read_conn(struct mg_connection *c, struct pkt *pkt) { } else if (pkt->pay.len == 0) { // TODO(cpq): handle this peer's ACK } else if (seq != s->ack) { - // TODO(cpq): peer sent us SEQ which we don't expect. Retransmit rather - // than close this connection - mg_error(c, "SEQ != ACK: %x %x", seq, s->ack); + uint32_t ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len); + if (s->ack == ack) { + MG_VERBOSE(("ignoring duplicate pkt")); + } else { + // TODO(cpq): peer sent us SEQ which we don't expect. Retransmit rather + // than close this connection + mg_error(c, "SEQ != ACK: %x %x %x", seq, s->ack, ack); + } } else if (io->size - io->len < pkt->pay.len && !mg_iobuf_resize(io, io->len + pkt->pay.len)) { mg_error(c, "oom");