From 88dac12ddb912883af7b52f6f27aa7ac86b86daf Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 21 Dec 2023 22:12:11 +0700 Subject: [PATCH] reduce CONFIG_LWIP_MAX_SOCKETS from 10 to 8 to save sram for ssl connection --- arduino/libraries/WiFi/src/WiFiSSLClient.cpp | 127 ++++++++----------- arduino/libraries/WiFi/src/WiFiSSLClient.h | 7 +- main/CommandHandler.cpp | 7 +- main/sketch.ino.cpp | 2 +- sdkconfig | 14 +- 5 files changed, 69 insertions(+), 88 deletions(-) diff --git a/arduino/libraries/WiFi/src/WiFiSSLClient.cpp b/arduino/libraries/WiFi/src/WiFiSSLClient.cpp index 313d8762..ffe1c9cb 100644 --- a/arduino/libraries/WiFi/src/WiFiSSLClient.cpp +++ b/arduino/libraries/WiFi/src/WiFiSSLClient.cpp @@ -17,8 +17,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Arduino.h" -#include #include #include #include "esp_partition.h" @@ -54,101 +52,78 @@ WiFiSSLClient::WiFiSSLClient() : int WiFiSSLClient::connect(const char* host, uint16_t port, bool sni) { - ets_printf("** Connect(host/port) Called\n"); - return connect(host, port, _cert, _private_key); -} - -int WiFiSSLClient::connect(const char* host, uint16_t port, const char* client_cert, const char* client_key) -{ - ets_printf("** Connect(host/port/cert/key) called\n"); - int ret, flags; synchronized { _netContext.fd = -1; _connected = false; - ets_printf("Free internal heap before TLS %u\n", heap_caps_get_free_size(MALLOC_CAP_8BIT)); - + // free heap should be 140KB for this connect ssl to work + ets_printf("Free heap before TLS %u\n", heap_caps_get_free_size(MALLOC_CAP_8BIT)); ets_printf("*** connect init\n"); - // SSL Client Initialization + mbedtls_ssl_init(&_sslContext); mbedtls_ctr_drbg_init(&_ctrDrbgContext); mbedtls_ssl_config_init(&_sslConfig); - + mbedtls_entropy_init(&_entropyContext); + mbedtls_x509_crt_init(&_caCrt); mbedtls_net_init(&_netContext); - ets_printf("*** connect inited\n"); - - ets_printf("*** connect drbgseed\n"); - mbedtls_entropy_init(&_entropyContext); // Seeds and sets up CTR_DRBG for future reseeds, pers is device personalization (esp) - ret = mbedtls_ctr_drbg_seed(&_ctrDrbgContext, mbedtls_entropy_func, - &_entropyContext, (const unsigned char *) pers, strlen(pers)); - if (ret < 0) { + const char *pers = "esp32-tls"; + if (mbedtls_ctr_drbg_seed(&_ctrDrbgContext, mbedtls_entropy_func, &_entropyContext, (const unsigned char *) pers, strlen(pers)) != 0) { ets_printf("Unable to set up mbedtls_entropy.\n"); stop(); return 0; } - ets_printf("*** connect ssl hostname\n"); - /* Hostname set here should match CN in server certificate */ - if(mbedtls_ssl_set_hostname(&_sslContext, host) != 0) { + if (mbedtls_ssl_config_defaults(&_sslConfig, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) != 0) { + ets_printf("Error Setting up SSL Config\n"); stop(); return 0; } - ets_printf("*** connect ssl config\n"); - ret= mbedtls_ssl_config_defaults(&_sslConfig, MBEDTLS_SSL_IS_CLIENT, - MBEDTLS_SSL_TRANSPORT_STREAM, - MBEDTLS_SSL_PRESET_DEFAULT); - if (ret != 0) { - stop(); - ets_printf("Error Setting up SSL Config: %d\n", ret); - return 0; - } - - ets_printf("*** connect authmode\n"); // we're always using the root CA cert from partition, so MBEDTLS_SSL_VERIFY_REQUIRED - ets_printf("*** Loading CA Cert...\n"); - mbedtls_x509_crt_init(&_caCrt); mbedtls_ssl_conf_authmode(&_sslConfig, MBEDTLS_SSL_VERIFY_REQUIRED); // setting up CA certificates from partition + ets_printf("*** Loading CA Cert...\n"); spi_flash_mmap_handle_t handle; const unsigned char* certs_data = {}; - ets_printf("*** connect part findfirst\n"); + const esp_partition_t* part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "certs"); if (part == NULL) { stop(); return 0; } - ets_printf("*** connect part mmap\n"); int ret = esp_partition_mmap(part, 0, part->size, SPI_FLASH_MMAP_DATA, (const void**)&certs_data, &handle); if (ret != ESP_OK) { ets_printf("*** Error partition mmap %d\n", ret); stop(); return 0; } + ets_printf(" Length of certs_data: %d\n", strlen((char*)certs_data)+1); - ets_printf("Length of certs_data: %d\n", strlen((char*)certs_data)+1); + // mbedtls_x509_crt_parse() requires ~92000 bytes from heap ets_printf("*** connect crt parse\n"); + ets_printf(" Free heap before: %u\n", heap_caps_get_free_size(MALLOC_CAP_8BIT)); ret = mbedtls_x509_crt_parse(&_caCrt, certs_data, strlen((char*)certs_data) + 1); - ets_printf("*** connect conf ca chain\n"); - mbedtls_ssl_conf_ca_chain(&_sslConfig, &_caCrt, NULL); if (ret < 0) { ets_printf("*** Error parsing CA chain.\n"); stop(); return 0; } + ets_printf(" Free heap after : %u\n", heap_caps_get_free_size(MALLOC_CAP_8BIT)); - ets_printf("*** check for client_cert and client_key\n"); - if (client_cert != NULL && client_key != NULL) { + mbedtls_ssl_conf_ca_chain(&_sslConfig, &_caCrt, NULL); + + ets_printf("*** check for _cert and _private_key\n"); + if (_cert != NULL && _private_key != NULL) { mbedtls_x509_crt_init(&_clientCrt); mbedtls_pk_init(&_clientKey); ets_printf("*** Loading client certificate.\n"); // note: +1 added for line ending - ret = mbedtls_x509_crt_parse(&_clientCrt, (const unsigned char *)client_cert, strlen(client_cert) + 1); + ret = mbedtls_x509_crt_parse(&_clientCrt, (const unsigned char *)_cert, strlen(_cert) + 1); if (ret != 0) { ets_printf("ERROR: Client cert not parsed properly(%d)\n", ret); stop(); @@ -156,7 +131,7 @@ int WiFiSSLClient::connect(const char* host, uint16_t port, const char* client_c } ets_printf("*** Loading private key.\n"); - ret = mbedtls_pk_parse_key(&_clientKey, (const unsigned char *)client_key, strlen(client_key)+1, + ret = mbedtls_pk_parse_key(&_clientKey, (const unsigned char *)_private_key, strlen(_private_key)+1, NULL, 0); if (ret != 0) { ets_printf("ERROR: Private key not parsed properly:(%d)\n", ret); @@ -166,7 +141,7 @@ int WiFiSSLClient::connect(const char* host, uint16_t port, const char* client_c // set own certificate chain and key ret = mbedtls_ssl_conf_own_cert(&_sslConfig, &_clientCrt, &_clientKey); if (ret != 0) { - if (ret == -0x7f00) { + if (ret == MBEDTLS_ERR_SSL_ALLOC_FAILED) { ets_printf("ERROR: Memory allocation failed, MBEDTLS_ERR_SSL_ALLOC_FAILED"); } ets_printf("Private key not parsed properly(%d)\n", ret); @@ -178,20 +153,21 @@ int WiFiSSLClient::connect(const char* host, uint16_t port, const char* client_c ets_printf("Client certificate and key not provided.\n"); } - ets_printf("*** connect conf RNG\n"); mbedtls_ssl_conf_rng(&_sslConfig, mbedtls_ctr_drbg_random, &_ctrDrbgContext); + // mbedtls_ssl_setup() requires ~36000 bytes from heap ets_printf("*** connect ssl setup\n"); + ets_printf(" Free heap before: %u\n", heap_caps_get_free_size(MALLOC_CAP_8BIT)); if ((ret = mbedtls_ssl_setup(&_sslContext, &_sslConfig)) != 0) { - if (ret == -0x7f00){ - ets_printf("%s", &_clientCrt); - ets_printf("Memory allocation failed (MBEDTLS_ERR_SSL_ALLOC_FAILED)\n"); - ets_printf("Free internal heap: %u\n", heap_caps_get_free_size(MALLOC_CAP_8BIT)); - } ets_printf("Unable to connect ssl setup %d\n", ret); + if (ret == MBEDTLS_ERR_SSL_ALLOC_FAILED){ + ets_printf(" Memory allocation failed (MBEDTLS_ERR_SSL_ALLOC_FAILED)\n"); + ets_printf(" %s", &_clientCrt); + } stop(); return 0; } + ets_printf(" Free heap after : %u\n", heap_caps_get_free_size(MALLOC_CAP_8BIT)); if (sni && mbedtls_ssl_set_hostname(&_sslContext, host) != 0) { stop(); @@ -200,36 +176,40 @@ int WiFiSSLClient::connect(const char* host, uint16_t port, const char* client_c char portStr[6]; itoa(port, portStr, 10); - ets_printf("*** connect netconnect\n"); + if (mbedtls_net_connect(&_netContext, host, portStr, MBEDTLS_NET_PROTO_TCP) != 0) { stop(); return 0; } - ets_printf("*** connect set bio\n"); mbedtls_ssl_set_bio(&_sslContext, &_netContext, mbedtls_net_send, mbedtls_net_recv, NULL); + // mbedtls_ssl_handshake() requires ~5600 bytes from heap ets_printf("*** start SSL/TLS handshake...\n"); - unsigned long start_handshake = millis(); - // ref: https://tls.mbed.org/api/ssl_8h.html#a4a37e497cd08c896870a42b1b618186e - while ((ret = mbedtls_ssl_handshake(&_sslContext)) !=0) { - if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - ets_printf("Error performing SSL handshake\n"); - } - if((millis() - start_handshake) > _handshake_timeout){ - ets_printf("SSL Handshake Timeout\n"); - stop(); - return -1; + ets_printf(" Free heap before: %u\n", heap_caps_get_free_size(MALLOC_CAP_8BIT)); + do { + ret = mbedtls_ssl_handshake(&_sslContext); + } while (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE); + ets_printf(" Free heap after : %u\n", heap_caps_get_free_size(MALLOC_CAP_8BIT)); + + if (ret != 0) { + ets_printf("Error performing SSL handshake %d\n", ret); + if (ret == MBEDTLS_ERR_SSL_ALLOC_FAILED) { + ets_printf(" Memory allocation failed (MBEDTLS_ERR_SSL_ALLOC_FAILED)\n"); + } else if (ret == MBEDTLS_ERR_X509_ALLOC_FAILED){ + ets_printf( "X509 allocation failed (MBEDTLS_ERR_X509_ALLOC_FAILED)\n"); } - vTaskDelay(10 / portTICK_PERIOD_MS); + stop(); + return 0; } - if (client_cert != NULL && client_key != NULL) - { + + if (_cert != NULL && _private_key != NULL) { ets_printf("Protocol is %s Ciphersuite is %s", mbedtls_ssl_get_version(&_sslContext), mbedtls_ssl_get_ciphersuite(&_sslContext)); } ets_printf("Verifying peer X.509 certificate\n"); char buf[512]; + int flags; if ((flags = mbedtls_ssl_get_verify_result(&_sslContext)) != 0) { bzero(buf, sizeof(buf)); mbedtls_x509_crt_verify_info(buf, sizeof(buf), " ! ", flags); @@ -240,22 +220,23 @@ int WiFiSSLClient::connect(const char* host, uint16_t port, const char* client_c ets_printf("Certificate chain verified.\n"); } - ets_printf("*** ssl set nonblock\n"); mbedtls_net_set_nonblock(&_netContext); - ets_printf("Free internal heap before cleanup: %u\n", heap_caps_get_free_size(MALLOC_CAP_8BIT)); // free the heap + ets_printf("Free heap before cleanup: %u\n", heap_caps_get_free_size(MALLOC_CAP_8BIT)); if (certs_data != NULL) { mbedtls_x509_crt_free(&_caCrt); } - if (client_cert != NULL) { + if (_cert != NULL) { mbedtls_x509_crt_free(&_clientCrt); } - if (client_key !=NULL) { + if (_private_key !=NULL) { mbedtls_pk_free(&_clientKey); } - ets_printf("Free internal heap after cleanup: %u\n", heap_caps_get_free_size(MALLOC_CAP_8BIT)); + ets_printf("Free heap after cleanup : %u\n", heap_caps_get_free_size(MALLOC_CAP_8BIT)); + _connected = true; + return 1; } } diff --git a/arduino/libraries/WiFi/src/WiFiSSLClient.h b/arduino/libraries/WiFi/src/WiFiSSLClient.h index bd114746..b55da9f8 100644 --- a/arduino/libraries/WiFi/src/WiFiSSLClient.h +++ b/arduino/libraries/WiFi/src/WiFiSSLClient.h @@ -22,14 +22,13 @@ #include #include -#include #include #include #include -#include #include - +// #include +// #include class WiFiSSLClient /*: public Client*/ { @@ -40,7 +39,6 @@ class WiFiSSLClient /*: public Client*/ { virtual int connect(/*IPAddress*/uint32_t ip, uint16_t port); virtual int connect(const char* host, uint16_t port); - virtual int connect(const char* host, uint16_t port, const char* client_cert, const char* client_key); virtual size_t write(uint8_t); virtual size_t write(const uint8_t *buf, size_t size); virtual int available(); @@ -59,7 +57,6 @@ class WiFiSSLClient /*: public Client*/ { virtual /*IPAddress*/uint32_t remoteIP(); virtual uint16_t remotePort(); - const char *pers = "esp32-tls"; private: int connect(const char* host, uint16_t port, bool sni); diff --git a/main/CommandHandler.cpp b/main/CommandHandler.cpp index 39db0ffb..479d37b2 100644 --- a/main/CommandHandler.cpp +++ b/main/CommandHandler.cpp @@ -45,7 +45,7 @@ int errno; #include "Arduino.h" // Note: following version definition line is parsed by python script. Please don't change its format (space, indent) only update its version number. -const char FIRMWARE_VERSION[6] = "1.7.7"; +const char FIRMWARE_VERSION[6] = "1.8.0"; // Optional, user-defined X.509 certificate char CERT_BUF[1300]; @@ -956,6 +956,7 @@ int getIdxChannel(const uint8_t command[], uint8_t response[]) return 6; } +// TODO Adafruit: conflict command ID with setClientCert(), currently not used int setEnt(const uint8_t command[], uint8_t response[]) { const uint8_t* commandPtr = &command[3]; @@ -1245,7 +1246,8 @@ int getDigitalRead(const uint8_t command[], uint8_t response[]) return 6; } -#if 1 +#if 1 +// Adafruit implementation int getAnalogRead(const uint8_t command[], uint8_t response[]) { uint8_t pin = command[4]; @@ -1262,6 +1264,7 @@ int getAnalogRead(const uint8_t command[], uint8_t response[]) } #else +// Arduino implemenation ADC is 2 bytes extern "C" { #include } diff --git a/main/sketch.ino.cpp b/main/sketch.ino.cpp index 7600741b..0b05c0dd 100644 --- a/main/sketch.ino.cpp +++ b/main/sketch.ino.cpp @@ -140,8 +140,8 @@ void setupBluetooth() { uart_set_pin(UART_NUM_1, 1, 3, 33, 12); // TX, RX, RTS, CTS #else uart_set_pin(UART_NUM_1, 23, 12, 18, 5); - uart_set_hw_flow_ctrl(UART_NUM_1, UART_HW_FLOWCTRL_CTS_RTS, 5); #endif + uart_set_hw_flow_ctrl(UART_NUM_1, UART_HW_FLOWCTRL_CTS_RTS, 5); if (debug) ets_printf("setup controller\n"); diff --git a/sdkconfig b/sdkconfig index 48a88a1c..c468fdf6 100644 --- a/sdkconfig +++ b/sdkconfig @@ -315,8 +315,8 @@ CONFIG_ESP32_WIFI_IRAM_OPT=y # # PHY # -CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE= -CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION=y +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION= CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 CONFIG_ESP32_PHY_MAX_TX_POWER=20 @@ -476,11 +476,11 @@ CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y # CONFIG_LOG_DEFAULT_LEVEL_NONE= CONFIG_LOG_DEFAULT_LEVEL_ERROR= -CONFIG_LOG_DEFAULT_LEVEL_WARN=y -CONFIG_LOG_DEFAULT_LEVEL_INFO= +CONFIG_LOG_DEFAULT_LEVEL_WARN= +CONFIG_LOG_DEFAULT_LEVEL_INFO=y CONFIG_LOG_DEFAULT_LEVEL_DEBUG= CONFIG_LOG_DEFAULT_LEVEL_VERBOSE= -CONFIG_LOG_DEFAULT_LEVEL=2 +CONFIG_LOG_DEFAULT_LEVEL=3 CONFIG_LOG_COLORS=y # @@ -488,7 +488,7 @@ CONFIG_LOG_COLORS=y # CONFIG_L2_TO_L3_COPY= CONFIG_LWIP_IRAM_OPTIMIZATION=y -CONFIG_LWIP_MAX_SOCKETS=10 +CONFIG_LWIP_MAX_SOCKETS=8 CONFIG_USE_ONLY_LWIP_SELECT= CONFIG_LWIP_SO_REUSE=y CONFIG_LWIP_SO_REUSE_RXTOALL=y @@ -500,7 +500,7 @@ CONFIG_LWIP_ETHARP_TRUST_IP_MAC=y CONFIG_ESP_GRATUITOUS_ARP=y CONFIG_GARP_TMR_INTERVAL=60 CONFIG_TCPIP_RECVMBOX_SIZE=32 -CONFIG_LWIP_DHCP_DOES_ARP_CHECK= +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y CONFIG_LWIP_DHCP_RESTORE_LAST_IP= #