1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-06-13 13:01:55 +03:00

Fix memory related issues w/BearSSL server/client (#5706)

Because the constructors of the BSSL client and server add a reference
count to the stack_thunk, if there is no copy constructor defined then
the stack thunk reference count can get out of sync causing the stack
thunk memory to be freed while still in use.  That could cause random
crashes or hangs.

Add a very basic copy constructor to the WiFiClientSecure and
WiFiServerSecure objects, using the default operator= to duplicate
simple types and shared_ptr classes.

The _cipher_list element (used only w/custom ciphers) could be freed
while still in use if copies of the WiFiClientSecure object were made.

Use a shared_ptr which will only free when the last reference is
deleted.

The axTLS compatibility mode calls allocate and store elements needed
for SSL connections (unlike normal BearSSL calls).  These elements could
be freed mistakenly while still in use if copies of the WiFiClientSecure
were made by the app.

Convert to a separately managed shared_ptr to ensure they live as long
as any referencing objects before deletion.

Same done for the axTLS compatability for WiFiServerSecure.
This commit is contained in:
Earle F. Philhower, III
2019-02-02 18:09:19 +00:00
committed by GitHub
parent 1cacf92ce1
commit 56268b166d
4 changed files with 63 additions and 60 deletions

View File

@ -49,13 +49,15 @@ WiFiServerSecure::WiFiServerSecure(uint16_t port) : WiFiServer(port) {
stack_thunk_add_ref();
}
// Destructor only checks if we need to delete compatibilty cert/key
WiFiServerSecure::WiFiServerSecure(const WiFiServerSecure &rhs) : WiFiServer(rhs) {
*this = rhs;
stack_thunk_add_ref();
}
WiFiServerSecure::~WiFiServerSecure() {
stack_thunk_del_ref();
if (_deleteChainAndKey) {
delete _chain;
delete _sk;
}
_axtls_chain = nullptr;
_axtls_sk = nullptr;
}
// Specify a RSA-signed certificate and key for the server. Only copies the pointer, the
@ -76,8 +78,6 @@ void WiFiServerSecure::setECCert(const X509List *chain, unsigned cert_issuer_key
// Return a client if there's an available connection waiting. If one is returned,
// then any validation (i.e. client cert checking) will have succeeded.
WiFiClientSecure WiFiServerSecure::available(uint8_t* status) {
WiFiClientSecure client;
(void) status; // Unused
if (_unclaimed) {
if (_sk && _sk->isRSA()) {
@ -85,35 +85,31 @@ WiFiClientSecure WiFiServerSecure::available(uint8_t* status) {
_unclaimed = _unclaimed->next();
result.setNoDelay(_noDelay);
DEBUGV("WS:av\r\n");
client = result;
return result;
} else if (_sk && _sk->isEC()) {
WiFiClientSecure result(_unclaimed, _chain, _cert_issuer_key_type, _sk, _iobuf_in_size, _iobuf_out_size, _client_CA_ta);
_unclaimed = _unclaimed->next();
result.setNoDelay(_noDelay);
DEBUGV("WS:av\r\n");
client = result;
return result;
} else {
// No key was defined, so we can't actually accept and attempt accept() and SSL handshake.
DEBUGV("WS:nokey\r\n");
}
} else {
optimistic_yield(1000);
}
return client;
// Something weird, return a no-op object
optimistic_yield(1000);
return WiFiClientSecure();
}
void WiFiServerSecure::setServerKeyAndCert(const uint8_t *key, int keyLen, const uint8_t *cert, int certLen) {
X509List *chain = new X509List(cert, certLen);
PrivateKey *sk = new PrivateKey(key, keyLen);
if (!chain || !key) {
// OOM, fail gracefully
delete chain;
delete sk;
return;
}
_deleteChainAndKey = true;
setRSACert(chain, sk);
_axtls_chain = nullptr;
_axtls_sk = nullptr;
_axtls_chain = std::shared_ptr<X509List>(new X509List(cert, certLen));
_axtls_sk = std::shared_ptr<PrivateKey>(new PrivateKey(key, keyLen));
setRSACert(_axtls_chain.get(), _axtls_sk.get());
}
void WiFiServerSecure::setServerKeyAndCert_P(const uint8_t *key, int keyLen, const uint8_t *cert, int certLen) {