Merge pull request #2000 from cesanta/tls

Add TLS to pico-w5500 baremetal example
This commit is contained in:
Sergio R. Caprile 2023-01-30 18:37:00 -03:00 committed by GitHub
commit d1c9d7ffdc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 152 additions and 22 deletions

View File

@ -10,7 +10,7 @@ int main(void) {
struct mg_mgr mgr; struct mg_mgr mgr;
mg_log_set(MG_LL_DEBUG); // Set debug log level mg_log_set(MG_LL_DEBUG); // Set debug log level
mg_mgr_init(&mgr); 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)); MG_INFO(("Listening on %s", s_listening_url));
while (mgr.conns != NULL) mg_mgr_poll(&mgr, 500); while (mgr.conns != NULL) mg_mgr_poll(&mgr, 500);
mg_mgr_free(&mgr); mg_mgr_free(&mgr);

View File

@ -9,7 +9,27 @@
#define MQTT_PUBLISH_TOPIC "mg/my_device" #define MQTT_PUBLISH_TOPIC "mg/my_device"
#define MQTT_SUBSCRIBE_TOPIC "mg/#" #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 #ifndef DISABLE_ROUTING
static struct mg_connection *s_sntp_conn = NULL; // SNTP connection static struct mg_connection *s_sntp_conn = NULL; // SNTP connection
#endif #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.url = strdup(MQTT_SERVER);
s_config.pub = strdup(MQTT_PUBLISH_TOPIC); s_config.pub = strdup(MQTT_PUBLISH_TOPIC);
s_config.sub = strdup(MQTT_SUBSCRIBE_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) { } else if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data; struct mg_http_message *hm = (struct mg_http_message *) ev_data;
struct user *u = getuser(hm); 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, "pub", &s_config.pub);
update_config(&hm->body, "sub", &s_config.sub); update_config(&hm->body, "sub", &s_config.sub);
if (s_mqtt) s_mqtt->is_closing = 1; // Ask to disconnect from MQTT 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"); mg_http_reply(c, 200, "", "ok\n");
} else { } else {
mg_http_reply(c, 403, "", "Denied\n"); mg_http_reply(c, 403, "", "Denied\n");

View File

@ -30,6 +30,6 @@ void app_main(void) {
mg_log_set(MG_LL_DEBUG); // Set log level mg_log_set(MG_LL_DEBUG); // Set log level
mg_mgr_init(&mgr); mg_mgr_init(&mgr);
MG_INFO(("Mongoose v%s on %s", MG_VERSION, s_listening_url)); 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 for (;;) mg_mgr_poll(&mgr, 1000); // Infinite event loop
} }

View File

@ -104,7 +104,7 @@ int main(int argc, char *argv[]) {
MG_INFO(("Listening on : %s", s_listening_address)); MG_INFO(("Listening on : %s", s_listening_address));
extern void device_dashboard_fn(struct mg_connection *, int, void *, void *); 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 while (s_signo == 0) mg_mgr_poll(&mgr, 100); // Infinite event loop

View File

@ -69,7 +69,7 @@ int main(void) {
MG_INFO(("Initialising application...")); MG_INFO(("Initialising application..."));
extern void device_dashboard_fn(struct mg_connection *, int, void *, void *); 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")); MG_INFO(("Starting event loop"));
for (;;) { for (;;) {

View File

@ -4,12 +4,15 @@ include(pico-sdk/pico_sdk_init.cmake)
project(firmware) project(firmware)
pico_sdk_init() pico_sdk_init()
file(GLOB TLS_SOURCES "mbedtls/library/*.c")
add_executable(firmware add_executable(firmware
main.c main.c
../../../mongoose.c ../../../mongoose.c
../../device-dashboard/net.c ../../device-dashboard/net.c
../../device-dashboard/packed_fs.c) ../../device-dashboard/packed_fs.c
target_include_directories(firmware PUBLIC ../../..) ${TLS_SOURCES})
target_include_directories(firmware PUBLIC . ../../.. mbedtls/include)
target_link_libraries(firmware pico_stdlib hardware_spi) target_link_libraries(firmware pico_stdlib hardware_spi)
pico_add_extra_outputs(firmware) 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_MIP=1)
add_definitions(-DMG_ENABLE_PACKED_FS=1) add_definitions(-DMG_ENABLE_PACKED_FS=1)
add_definitions(-DMG_ENABLE_FILE=0) 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)

View File

@ -1,7 +1,9 @@
SDK_VERSION ?= 1.4.0 SDK_VERSION ?= 1.4.0
SDK_REPO ?= https://github.com/raspberrypi/pico-sdk 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 test -d build || mkdir build
cd build && cmake .. && make cd build && cmake .. && make
@ -9,6 +11,9 @@ pico-sdk:
git clone --depth 1 -b $(SDK_VERSION) $(SDK_REPO) $@ git clone --depth 1 -b $(SDK_VERSION) $(SDK_REPO) $@
cd $@ && git submodule update --init cd $@ && git submodule update --init
mbedtls:
git clone --depth 1 -b $(MBEDTLS_VERSION) $(MBEDTLS_REPO) $@
# Requires env variable VCON_API_KEY set # Requires env variable VCON_API_KEY set
DEVICE_URL ?= https://dash.vcon.io/api/v3/devices/3 DEVICE_URL ?= https://dash.vcon.io/api/v3/devices/3
test: update test: update
@ -20,4 +25,4 @@ update: build/firmware.uf2
curl --fail -su :$(VCON_API_KEY) $(DEVICE_URL)/ota?uf2=1 --data-binary @$< curl --fail -su :$(VCON_API_KEY) $(DEVICE_URL)/ota?uf2=1 --data-binary @$<
clean: clean:
rm -rf pico-sdk build rm -rf pico-sdk mbedtls build

View File

@ -60,7 +60,8 @@ int main(void) {
MG_INFO(("Initialising application...")); MG_INFO(("Initialising application..."));
extern void device_dashboard_fn(struct mg_connection *, int, void *, void *); 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")); MG_INFO(("Starting event loop"));
for (;;) { for (;;) {

View File

@ -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 <limits.h>
#include "mongoose.h"

View File

@ -85,7 +85,7 @@ int main(void) {
MG_INFO(("Initialising application...")); MG_INFO(("Initialising application..."));
extern void device_dashboard_fn(struct mg_connection *, int, void *, void *); 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")); MG_INFO(("Starting event loop"));
for (;;) { for (;;) {

View File

@ -80,7 +80,7 @@ int main(void) {
MG_INFO(("Init done, starting main loop")); MG_INFO(("Init done, starting main loop"));
extern void device_dashboard_fn(struct mg_connection *, int, void *, void *); 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 for (;;) mg_mgr_poll(&mgr, 0); // Infinite event loop
return 0; return 0;

View File

@ -101,7 +101,7 @@ int main(void) {
mg_timer_add(&mgr, 1000, MG_TIMER_REPEAT, blink_cb, &mif); mg_timer_add(&mgr, 1000, MG_TIMER_REPEAT, blink_cb, &mif);
extern void device_dashboard_fn(struct mg_connection *, int, void *, void *); 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 for (;;) mg_mgr_poll(&mgr, 0); // Infinite event loop
return 0; return 0;

View File

@ -27,7 +27,7 @@ int main(int argc, char *argv[]) {
mg_mgr_init(&mgr); mg_mgr_init(&mgr);
extern void device_dashboard_fn(struct mg_connection *, int, void *, void *); 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 // Start infinite event loop
MG_INFO(("Mongoose version : v%s", MG_VERSION)); MG_INFO(("Mongoose version : v%s", MG_VERSION));

View File

@ -609,9 +609,14 @@ static void read_conn(struct mg_connection *c, struct pkt *pkt) {
} else if (pkt->pay.len == 0) { } else if (pkt->pay.len == 0) {
// TODO(cpq): handle this peer's ACK // TODO(cpq): handle this peer's ACK
} else if (seq != s->ack) { } else if (seq != s->ack) {
// TODO(cpq): peer sent us SEQ which we don't expect. Retransmit rather uint32_t ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len);
// than close this connection if (s->ack == ack) {
mg_error(c, "SEQ != ACK: %x %x", seq, s->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 && } else if (io->size - io->len < pkt->pay.len &&
!mg_iobuf_resize(io, io->len + pkt->pay.len)) { !mg_iobuf_resize(io, io->len + pkt->pay.len)) {
mg_error(c, "oom"); mg_error(c, "oom");

View File

@ -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(20) | BIT(28) | BIT(29) | BIT(30); // Chain,FS,LS
s_txdesc[s_txno][0] |= BIT(31); // Set OWN bit - let DMA take over s_txdesc[s_txno][0] |= BIT(31); // Set OWN bit - let DMA take over
if (++s_txno >= ETH_DESC_CNT) s_txno = 0; if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
printf("sent\n");
} }
ETH->DMASR = BIT(2) | BIT(5); // Clear any prior TBUS/TUS ETH->DMASR = BIT(2) | BIT(5); // Clear any prior TBUS/TUS
ETH->DMATPDR = 0; // and resume 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; return bsr & BIT(2) ? 1 : 0;
} }
void ETH_IRQHandler(void);
static uint32_t s_rxno; static uint32_t s_rxno;
void ETH_IRQHandler(void);
void ETH_IRQHandler(void) { void ETH_IRQHandler(void) {
static int cnt;
printf("--> %d\n", cnt++);
qp_mark(QP_IRQTRIGGERED, 0); qp_mark(QP_IRQTRIGGERED, 0);
if (ETH->DMASR & BIT(6)) { // Frame received, loop if (ETH->DMASR & BIT(6)) { // Frame received, loop
ETH->DMASR = BIT(16) | BIT(6); // Clear flag 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) { } else if (pkt->pay.len == 0) {
// TODO(cpq): handle this peer's ACK // TODO(cpq): handle this peer's ACK
} else if (seq != s->ack) { } else if (seq != s->ack) {
// TODO(cpq): peer sent us SEQ which we don't expect. Retransmit rather uint32_t ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len);
// than close this connection if (s->ack == ack) {
mg_error(c, "SEQ != ACK: %x %x", seq, s->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 && } else if (io->size - io->len < pkt->pay.len &&
!mg_iobuf_resize(io, io->len + pkt->pay.len)) { !mg_iobuf_resize(io, io->len + pkt->pay.len)) {
mg_error(c, "oom"); mg_error(c, "oom");