mirror of
https://github.com/esp8266/Arduino.git
synced 2025-09-06 19:08:12 +03:00
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.
121 lines
4.0 KiB
C++
121 lines
4.0 KiB
C++
/*
|
|
WiFiServerBearSSL.cpp - SSL server for esp8266, mostly compatible
|
|
with Arduino WiFi shield library
|
|
|
|
Copyright (c) 2018 Earle F. Philhower, III
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#define LWIP_INTERNAL
|
|
|
|
extern "C" {
|
|
#include "osapi.h"
|
|
#include "ets_sys.h"
|
|
}
|
|
|
|
#include <StackThunk.h>
|
|
#include "debug.h"
|
|
#include "ESP8266WiFi.h"
|
|
#include "WiFiClient.h"
|
|
#include "WiFiServer.h"
|
|
#include "lwip/opt.h"
|
|
#include "lwip/tcp.h"
|
|
#include "lwip/inet.h"
|
|
#include <include/ClientContext.h>
|
|
#include "WiFiServerSecureBearSSL.h"
|
|
|
|
namespace BearSSL {
|
|
|
|
// Only need to call the standard server constructor
|
|
WiFiServerSecure::WiFiServerSecure(IPAddress addr, uint16_t port) : WiFiServer(addr, port) {
|
|
stack_thunk_add_ref();
|
|
}
|
|
|
|
// Only need to call the standard server constructor
|
|
WiFiServerSecure::WiFiServerSecure(uint16_t port) : WiFiServer(port) {
|
|
stack_thunk_add_ref();
|
|
}
|
|
|
|
WiFiServerSecure::WiFiServerSecure(const WiFiServerSecure &rhs) : WiFiServer(rhs) {
|
|
*this = rhs;
|
|
stack_thunk_add_ref();
|
|
}
|
|
|
|
WiFiServerSecure::~WiFiServerSecure() {
|
|
stack_thunk_del_ref();
|
|
_axtls_chain = nullptr;
|
|
_axtls_sk = nullptr;
|
|
}
|
|
|
|
// Specify a RSA-signed certificate and key for the server. Only copies the pointer, the
|
|
// caller needs to preserve this chain and key for the life of the object.
|
|
void WiFiServerSecure::setRSACert(const X509List *chain, const PrivateKey *sk) {
|
|
_chain = chain;
|
|
_sk = sk;
|
|
}
|
|
|
|
// Specify a EC-signed certificate and key for the server. Only copies the pointer, the
|
|
// caller needs to preserve this chain and key for the life of the object.
|
|
void WiFiServerSecure::setECCert(const X509List *chain, unsigned cert_issuer_key_type, const PrivateKey *sk) {
|
|
_chain = chain;
|
|
_cert_issuer_key_type = cert_issuer_key_type;
|
|
_sk = sk;
|
|
}
|
|
|
|
// 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) {
|
|
(void) status; // Unused
|
|
if (_unclaimed) {
|
|
if (_sk && _sk->isRSA()) {
|
|
WiFiClientSecure result(_unclaimed, _chain, _sk, _iobuf_in_size, _iobuf_out_size, _client_CA_ta);
|
|
_unclaimed = _unclaimed->next();
|
|
result.setNoDelay(_noDelay);
|
|
DEBUGV("WS:av\r\n");
|
|
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");
|
|
return result;
|
|
} else {
|
|
// No key was defined, so we can't actually accept and attempt accept() and SSL handshake.
|
|
DEBUGV("WS:nokey\r\n");
|
|
}
|
|
}
|
|
|
|
// 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) {
|
|
_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) {
|
|
setServerKeyAndCert(key, keyLen, cert, certLen);
|
|
}
|
|
|
|
|
|
};
|