Merge pull request #10576 from s-hadinger/esp32_tls

ESP32 support for TLS MQTT using BearSSL (same as ESP8266)
This commit is contained in:
s-hadinger 2021-01-15 18:48:13 +01:00 committed by GitHub
commit 16f3d30535
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 68 additions and 6 deletions

View File

@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file.
- Support for BS814A-2 8-button touch buttons by Peter Franck (#10447)
- Support for up to 4 I2C SEESAW_SOIL Capacitance & Temperature sensors by Peter Franck (#10481)
- ESP8266 Support for 2MB and up linker files with 1MB and up LittleFS
- ESP32 support for TLS MQTT using BearSSL (same as ESP8266)
### Breaking Changed
- ESP32 switch from default SPIFFS to default LittleFS file system loosing current (zigbee) files

View File

@ -28,6 +28,7 @@
#include "my_user_config.h"
#include "tasmota_configurations.h"
#if defined(ESP8266) && defined(USE_TLS)
#include <stdint.h>
#include <stdlib.h>
#include "StackThunk_light.h"
@ -145,3 +146,5 @@ void stack_thunk_light_fatal_overflow()
}
};
#endif

View File

@ -22,7 +22,7 @@
#include "my_user_config.h"
#include "tasmota_configurations.h"
#if defined(ESP8266) && defined(USE_TLS)
#if defined(USE_TLS)
// #define DEBUG_TLS
// #define DEBUG_ESP_SSL
@ -47,7 +47,9 @@ extern "C" {
#include "lwip/tcp.h"
#include "lwip/inet.h"
#include "lwip/netif.h"
#include <include/ClientContext.h>
#ifdef ESP8266
#include <include/ClientContext.h>
#endif
#include "c_types.h"
#include <core_version.h>
@ -57,11 +59,15 @@ extern "C" {
#include "coredecls.h"
#define LOG_HEAP_SIZE(a) _Log_heap_size(a)
void _Log_heap_size(const char *msg) {
#ifdef ESP8266
register uint32_t *sp asm("a1");
int freestack = 4 * (sp - g_pcont->stack);
Serial.printf("%s %d, Fragmentation=%d, Thunkstack=%d, Free stack=%d, FreeContStack=%d\n",
msg, ESP.getFreeHeap(), ESP.getHeapFragmentation(), stack_thunk_light_get_max_usage(),
freestack, ESP.getFreeContStack());
#elif defined(ESP32)
Serial.printf("> Heap %s = %d\n", msg, uxTaskGetStackHighWaterMark(nullptr));
#endif
}
#else
#define LOG_HEAP_SIZE(a)
@ -71,6 +77,7 @@ void _Log_heap_size(const char *msg) {
extern uint32_t UtcTime(void);
extern uint32_t CfgTime(void);
#ifdef ESP8266 // Stack thunk is not needed with ESP32
// Stack thunked versions of calls
// Initially in BearSSLHelpers.h
extern "C" {
@ -164,6 +171,8 @@ unsigned char *min_br_ssl_engine_sendrec_buf(const br_ssl_engine_context *cc, si
#define br_ssl_engine_sendrec_ack min_br_ssl_engine_sendrec_ack
#define br_ssl_engine_sendrec_buf min_br_ssl_engine_sendrec_buf
#endif // ESP8266
//#define DEBUG_ESP_SSL
#ifdef DEBUG_ESP_SSL
//#define DEBUG_BSSL(fmt, ...) DEBUG_ESP_PORT.printf_P((PGM_P)PSTR( "BSSL:" fmt), ## __VA_ARGS__)
@ -201,19 +210,23 @@ void WiFiClientSecure_light::_clear() {
// Constructor
WiFiClientSecure_light::WiFiClientSecure_light(int recv, int xmit) : WiFiClient() {
_clear();
LOG_HEAP_SIZE("StackThunk before");
// LOG_HEAP_SIZE("StackThunk before");
//stack_thunk_light_add_ref();
LOG_HEAP_SIZE("StackThunk after");
// LOG_HEAP_SIZE("StackThunk after");
// now finish the setup
setBufferSizes(recv, xmit); // reasonable minimum
allocateBuffers();
}
WiFiClientSecure_light::~WiFiClientSecure_light() {
#ifdef ESP8266
if (_client) {
_client->unref();
_client = nullptr;
}
#elif defined(ESP32)
stop();
#endif
//_cipher_list = nullptr; // std::shared will free if last reference
_freeSSL();
}
@ -258,6 +271,7 @@ void WiFiClientSecure_light::setBufferSizes(int recv, int xmit) {
_iobuf_out_size = xmit;
}
#ifdef ESP8266
bool WiFiClientSecure_light::stop(unsigned int maxWaitMs) {
bool ret = WiFiClient::stop(maxWaitMs); // calls our virtual flush()
_freeSSL();
@ -268,6 +282,17 @@ bool WiFiClientSecure_light::flush(unsigned int maxWaitMs) {
(void) _run_until(BR_SSL_SENDAPP);
return WiFiClient::flush(maxWaitMs);
}
#elif defined(ESP32)
void WiFiClientSecure_light::stop(void) {
WiFiClient::stop(); // calls our virtual flush()
_freeSSL();
}
void WiFiClientSecure_light::flush(void) {
(void) _run_until(BR_SSL_SENDAPP);
WiFiClient::flush();
}
#endif
int WiFiClientSecure_light::connect(IPAddress ip, uint16_t port) {
DEBUG_BSSL("connect(%s,%d)", ip.toString().c_str(), port);
@ -307,7 +332,11 @@ void WiFiClientSecure_light::_freeSSL() {
}
bool WiFiClientSecure_light::_clientConnected() {
#ifdef ESP8266
return (_client && _client->state() == ESTABLISHED);
#elif defined(ESP32)
return WiFiClient::connected();
#endif
}
uint8_t WiFiClientSecure_light::connected() {
@ -489,7 +518,7 @@ size_t WiFiClientSecure_light::peekBytes(uint8_t *buffer, size_t length) {
achieved, this function returns 0. On error, it returns -1.
*/
int WiFiClientSecure_light::_run_until(unsigned target, bool blocking) {
//LOG_HEAP_SIZE("_run_until 1");
//LOG_HEAP_SIZE("_run_until 1");
if (!ctx_present()) {
DEBUG_BSSL("_run_until: Not connected\n");
return -1;
@ -506,9 +535,15 @@ int WiFiClientSecure_light::_run_until(unsigned target, bool blocking) {
return -1;
}
#ifdef ESP8266
if (!(_client->state() == ESTABLISHED) && !WiFiClient::available()) {
return (state & target) ? 0 : -1;
}
#elif defined(ESP32)
if (!_clientConnected() && !WiFiClient::available()) {
return (state & target) ? 0 : -1;
}
#endif
/*
If there is some record data to send, do it. This takes
@ -898,12 +933,16 @@ bool WiFiClientSecure_light::_connectSSL(const char* hostName) {
do { // used to exit on Out of Memory error and keep all cleanup code at the same place
// ============================================================
// allocate Thunk stack, move to alternate stack and initialize
#ifdef ESP8266
stack_thunk_light_add_ref();
#endif // ESP8266
LOG_HEAP_SIZE("Thunk allocated");
DEBUG_BSSL("_connectSSL: start connection\n");
_freeSSL();
clearLastError();
if (!stack_thunk_light_get_stack_bot()) break;
#ifdef ESP8266
if (!stack_thunk_light_get_stack_bot()) break;
#endif // ESP8266
_ctx_present = true;
_eng = &_sc->eng; // Allocation/deallocation taken care of by the _sc shared_ptr
@ -964,10 +1003,12 @@ bool WiFiClientSecure_light::_connectSSL(const char* hostName) {
}
#endif
LOG_HEAP_SIZE("_connectSSL.end");
#ifdef ESP8266
_max_thunkstack_use = stack_thunk_light_get_max_usage();
stack_thunk_light_del_ref();
//stack_thunk_light_repaint();
LOG_HEAP_SIZE("_connectSSL.end, freeing StackThunk");
#endif // ESP8266
#ifdef USE_MQTT_TLS_CA_CERT
free(x509_minimal);
@ -982,7 +1023,9 @@ bool WiFiClientSecure_light::_connectSSL(const char* hostName) {
// if we arrived here, this means we had an OOM error, cleaning up
setLastError(ERR_OOM);
DEBUG_BSSL("_connectSSL: Out of memory\n");
#ifdef ESP8266
stack_thunk_light_del_ref();
#endif
#ifdef USE_MQTT_TLS_CA_CERT
free(x509_minimal);
#else

View File

@ -43,7 +43,11 @@ class WiFiClientSecure_light : public WiFiClient {
uint8_t connected() override;
size_t write(const uint8_t *buf, size_t size) override;
#ifdef ESP8266
size_t write_P(PGM_P buf, size_t size) override;
#else
size_t write_P(PGM_P buf, size_t size);
#endif
size_t write(const char *buf) {
return write((const uint8_t*)buf, strlen(buf));
}
@ -55,11 +59,17 @@ class WiFiClientSecure_light : public WiFiClient {
int available() override;
int read() override;
int peek() override;
#ifdef ESP8266
size_t peekBytes(uint8_t *buffer, size_t length) override;
bool flush(unsigned int maxWaitMs);
bool stop(unsigned int maxWaitMs);
void flush() override { (void)flush(0); }
void stop() override { (void)stop(0); }
#else
size_t peekBytes(uint8_t *buffer, size_t length);
void flush() override;
void stop() override;
#endif
// Only check SHA1 fingerprint of public key
void setPubKeyFingerprint(const uint8_t *f1, const uint8_t *f2,

View File

@ -679,8 +679,13 @@ void MqttReconnect(void) {
if (MqttClient.connect(TasmotaGlobal.mqtt_client, mqtt_user, mqtt_pwd, stopic, 1, lwt_retain, TasmotaGlobal.mqtt_data, MQTT_CLEAN_SESSION)) {
#ifdef USE_MQTT_TLS
if (Mqtt.mqtt_tls) {
#ifdef ESP8266
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "TLS connected in %d ms, max ThunkStack used %d"),
millis() - mqtt_connect_time, tlsClient->getMaxThunkStackUse());
#elif defined(ESP32)
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "TLS connected in %d ms, stack low mark %d"),
millis() - mqtt_connect_time, uxTaskGetStackHighWaterMark(nullptr));
#endif
if (!tlsClient->getMFLNStatus()) {
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "MFLN not supported by TLS server"));
}