From 51d66dae60b0c54d2e33d58ebf380f0b1aeaed33 Mon Sep 17 00:00:00 2001 From: M Hightower <27247790+mhightower83@users.noreply.github.com> Date: Thu, 8 Jul 2021 21:14:09 -0700 Subject: [PATCH] Fixes failing https connections to HelloServerBearSSL when using the MMU option with 48K IRAM shared. This happended after changes that increased IRAM code size that caused free IRAM for Heap to fall below ~16K, then "new" would OOM out in WiFiClientSecureBearSSL. Added private function to try IRAM first then switch to DRAM on fail to WiFiClientSecureBearSSL for iobuff allocations. --- .../src/WiFiClientSecureBearSSL.cpp | 58 +++++++++---------- .../ESP8266WiFi/src/WiFiClientSecureBearSSL.h | 5 +- 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp index d0e7c00fa0..6a82ff3b96 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp @@ -1083,6 +1083,17 @@ bool WiFiClientSecureCtx::_installClientX509Validator() { return true; } +std::shared_ptr WiFiClientSecureCtx::_alloc_iobuf(size_t sz) +{ // Allocate buffer with preference to IRAM + HeapSelectIram primary; + auto sptr = std::shared_ptr(new (std::nothrow) unsigned char[sz], std::default_delete()); + if (!sptr) { + HeapSelectDram alternate; + sptr = std::shared_ptr(new (std::nothrow) unsigned char[sz], std::default_delete()); + } + return sptr; +} + // Called by connect() to do the actual SSL setup and handshake. // Returns if the SSL handshake succeeded. bool WiFiClientSecureCtx::_connectSSL(const char* hostName) { @@ -1099,17 +1110,12 @@ bool WiFiClientSecureCtx::_connectSSL(const char* hostName) { _sc = std::make_shared(); _eng = &_sc->eng; // Allocation/deallocation taken care of by the _sc shared_ptr - //C This was borrowed from @earlephilhower PoC, to exemplify the use of IRAM. - //C Is this something we want to keep in the final release? - { // ESP.setIramHeap(); would be an alternative to using a class to set a scope for IRAM usage. - HeapSelectIram ephemeral; - _iobuf_in = std::shared_ptr(new (std::nothrow) unsigned char[_iobuf_in_size], std::default_delete()); - _iobuf_out = std::shared_ptr(new (std::nothrow) unsigned char[_iobuf_out_size], std::default_delete()); - DBG_MMU_PRINTF("\n_iobuf_in: %p\n", _iobuf_in.get()); - DBG_MMU_PRINTF( "_iobuf_out: %p\n", _iobuf_out.get()); - DBG_MMU_PRINTF( "_iobuf_in_size: %u\n", _iobuf_in_size); - DBG_MMU_PRINTF( "_iobuf_out_size: %u\n", _iobuf_out_size); - } // ESP.resetHeap(); + _iobuf_in = _alloc_iobuf(_iobuf_in_size); + _iobuf_out = _alloc_iobuf(_iobuf_out_size); + DBG_MMU_PRINTF("\n_iobuf_in: %p\n", _iobuf_in.get()); + DBG_MMU_PRINTF( "_iobuf_out: %p\n", _iobuf_out.get()); + DBG_MMU_PRINTF( "_iobuf_in_size: %u\n", _iobuf_in_size); + DBG_MMU_PRINTF( "_iobuf_out_size: %u\n", _iobuf_out_size); if (!_sc || !_iobuf_in || !_iobuf_out) { _freeSSL(); // Frees _sc, _iobuf* @@ -1225,15 +1231,12 @@ bool WiFiClientSecureCtx::_connectSSLServerRSA(const X509List *chain, _oom_err = false; _sc_svr = std::make_shared(); _eng = &_sc_svr->eng; // Allocation/deallocation taken care of by the _sc shared_ptr - { // ESP.setIramHeap(); - HeapSelectIram ephemeral; - _iobuf_in = std::shared_ptr(new (std::nothrow) unsigned char[_iobuf_in_size], std::default_delete()); - _iobuf_out = std::shared_ptr(new (std::nothrow) unsigned char[_iobuf_out_size], std::default_delete()); - DBG_MMU_PRINTF("\n_iobuf_in: %p\n", _iobuf_in.get()); - DBG_MMU_PRINTF( "_iobuf_out: %p\n", _iobuf_out.get()); - DBG_MMU_PRINTF( "_iobuf_in_size: %u\n", _iobuf_in_size); - DBG_MMU_PRINTF( "_iobuf_out_size: %u\n", _iobuf_out_size); - } // ESP.resetHeap(); + _iobuf_in = _alloc_iobuf(_iobuf_in_size); + _iobuf_out = _alloc_iobuf(_iobuf_out_size); + DBG_MMU_PRINTF("\n_iobuf_in: %p\n", _iobuf_in.get()); + DBG_MMU_PRINTF( "_iobuf_out: %p\n", _iobuf_out.get()); + DBG_MMU_PRINTF( "_iobuf_in_size: %u\n", _iobuf_in_size); + DBG_MMU_PRINTF( "_iobuf_out_size: %u\n", _iobuf_out_size); if (!_sc_svr || !_iobuf_in || !_iobuf_out) { _freeSSL(); @@ -1272,15 +1275,12 @@ bool WiFiClientSecureCtx::_connectSSLServerEC(const X509List *chain, _oom_err = false; _sc_svr = std::make_shared(); _eng = &_sc_svr->eng; // Allocation/deallocation taken care of by the _sc shared_ptr - { // ESP.setIramHeap(); - HeapSelectIram ephemeral; - _iobuf_in = std::shared_ptr(new (std::nothrow) unsigned char[_iobuf_in_size], std::default_delete()); - _iobuf_out = std::shared_ptr(new (std::nothrow) unsigned char[_iobuf_out_size], std::default_delete()); - DBG_MMU_PRINTF("\n_iobuf_in: %p\n", _iobuf_in.get()); - DBG_MMU_PRINTF( "_iobuf_out: %p\n", _iobuf_out.get()); - DBG_MMU_PRINTF( "_iobuf_in_size: %u\n", _iobuf_in_size); - DBG_MMU_PRINTF( "_iobuf_out_size: %u\n", _iobuf_out_size); - } // ESP.resetHeap(); + _iobuf_in = _alloc_iobuf(_iobuf_in_size); + _iobuf_out = _alloc_iobuf(_iobuf_out_size); + DBG_MMU_PRINTF("\n_iobuf_in: %p\n", _iobuf_in.get()); + DBG_MMU_PRINTF( "_iobuf_out: %p\n", _iobuf_out.get()); + DBG_MMU_PRINTF( "_iobuf_in_size: %u\n", _iobuf_in_size); + DBG_MMU_PRINTF( "_iobuf_out_size: %u\n", _iobuf_out_size); if (!_sc_svr || !_iobuf_in || !_iobuf_out) { _freeSSL(); diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.h b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.h index 166c29c603..73dc9e7337 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.h +++ b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.h @@ -189,6 +189,7 @@ class WiFiClientSecureCtx : public WiFiClient { size_t _recvapp_len; bool _clientConnected(); // Is the underlying socket alive? + std::shared_ptr _alloc_iobuf(size_t sz); void _freeSSL(); int _run_until(unsigned target, bool blocking = true); size_t _write(const uint8_t *buf, size_t size, bool pmem); @@ -309,8 +310,8 @@ class WiFiClientSecure : public WiFiClient { // Limit the TLS versions BearSSL will connect with. Default is // BR_TLS10...BR_TLS12. Allowed values are: BR_TLS10, BR_TLS11, BR_TLS12 - bool setSSLVersion(uint32_t min = BR_TLS10, uint32_t max = BR_TLS12) { return _ctx->setSSLVersion(min, max); }; - + bool setSSLVersion(uint32_t min = BR_TLS10, uint32_t max = BR_TLS12) { return _ctx->setSSLVersion(min, max); }; + // Check for Maximum Fragment Length support for given len before connection (possibly insecure) static bool probeMaxFragmentLength(IPAddress ip, uint16_t port, uint16_t len); static bool probeMaxFragmentLength(const char *hostname, uint16_t port, uint16_t len);