Skip to content

Commit

Permalink
reduce CONFIG_LWIP_MAX_SOCKETS from 10 to 8 to save sram for ssl conn…
Browse files Browse the repository at this point in the history
…ection
  • Loading branch information
hathach committed Dec 21, 2023
1 parent 338408f commit 88dac12
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 88 deletions.
127 changes: 54 additions & 73 deletions arduino/libraries/WiFi/src/WiFiSSLClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "Arduino.h"
#include <lwip/err.h>
#include <lwip/netdb.h>
#include <lwip/sockets.h>
#include "esp_partition.h"
Expand Down Expand Up @@ -54,109 +52,86 @@ 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();
return 0;
}

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);
Expand All @@ -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);
Expand All @@ -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();
Expand All @@ -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);
Expand All @@ -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;
}
}
Expand Down
7 changes: 2 additions & 5 deletions arduino/libraries/WiFi/src/WiFiSSLClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,13 @@

#include <mbedtls/net.h>
#include <mbedtls/ssl.h>
#include <mbedtls/platform.h>
#include <mbedtls/entropy.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/error.h>
#include <mbedtls/debug.h>

#include <Arduino.h>

// #include <Client.h>
// #include <IPAddress.h>

class WiFiSSLClient /*: public Client*/ {

Expand All @@ -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();
Expand All @@ -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);
Expand Down
7 changes: 5 additions & 2 deletions main/CommandHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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];
Expand All @@ -1262,6 +1264,7 @@ int getAnalogRead(const uint8_t command[], uint8_t response[])
}

#else
// Arduino implemenation ADC is 2 bytes
extern "C" {
#include <driver/adc.h>
}
Expand Down
2 changes: 1 addition & 1 deletion main/sketch.ino.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");

Expand Down
14 changes: 7 additions & 7 deletions sdkconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -476,19 +476,19 @@ 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

#
# LWIP
#
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
Expand All @@ -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=

#
Expand Down

0 comments on commit 88dac12

Please sign in to comment.