1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-07-18 23:03:34 +03:00

Merge branch 'master' into feature/issue-2246-multi-wifi-hidden

This commit is contained in:
Erriez
2021-01-19 16:12:54 +01:00
committed by GitHub
354 changed files with 21094 additions and 34937 deletions

View File

@ -526,6 +526,10 @@ namespace brssl {
case BR_KEYTYPE_EC:
ek = br_skey_decoder_get_ec(dc.get());
sk = (private_key*)malloc(sizeof * sk);
if (!sk)
{
return nullptr;
}
sk->key_type = BR_KEYTYPE_EC;
sk->key.ec.curve = ek->curve;
sk->key.ec.x = (uint8_t*)malloc(ek->xlen);
@ -626,6 +630,17 @@ namespace brssl {
return pk;
}
static uint8_t *loadStream(Stream& stream, size_t size) {
uint8_t *dest = (uint8_t *)malloc(size);
if (!dest) {
return nullptr; // OOM error
}
if (size != stream.readBytes(dest, size)) {
free(dest); // Error during read
return nullptr;
}
return dest;
}
};
@ -648,6 +663,15 @@ PublicKey::PublicKey(const uint8_t *derKey, size_t derLen) {
parse(derKey, derLen);
}
PublicKey::PublicKey(Stream &stream, size_t size) {
_key = nullptr;
auto buff = brssl::loadStream(stream, size);
if (buff) {
parse(buff, size);
free(buff);
}
}
PublicKey::~PublicKey() {
if (_key) {
brssl::free_public_key(_key);
@ -711,6 +735,15 @@ PrivateKey::PrivateKey(const uint8_t *derKey, size_t derLen) {
parse(derKey, derLen);
}
PrivateKey::PrivateKey(Stream &stream, size_t size) {
_key = nullptr;
auto buff = brssl::loadStream(stream, size);
if (buff) {
parse(buff, size);
free(buff);
}
}
PrivateKey::~PrivateKey() {
if (_key) {
brssl::free_private_key(_key);
@ -781,6 +814,17 @@ X509List::X509List(const uint8_t *derCert, size_t derLen) {
append(derCert, derLen);
}
X509List::X509List(Stream &stream, size_t size) {
_count = 0;
_cert = nullptr;
_ta = nullptr;
auto buff = brssl::loadStream(stream, size);
if (buff) {
append(buff, size);
free(buff);
}
}
X509List::~X509List() {
brssl::free_certificates(_cert, _count); // also frees cert
for (size_t i = 0; i < _count; i++) {
@ -832,6 +876,22 @@ bool X509List::append(const uint8_t *derCert, size_t derLen) {
return true;
}
ServerSessions::~ServerSessions() {
if (_isDynamic && _store != nullptr)
delete _store;
}
ServerSessions::ServerSessions(ServerSession *sessions, uint32_t size, bool isDynamic) :
_size(sessions != nullptr ? size : 0),
_store(sessions), _isDynamic(isDynamic) {
if (_size > 0)
br_ssl_session_cache_lru_init(&_cache, (uint8_t*)_store, size * sizeof(ServerSession));
}
const br_ssl_session_cache_class **ServerSessions::getCache() {
return _size > 0 ? &_cache.vtable : nullptr;
}
// SHA256 hash for updater
void HashSHA256::begin() {
br_sha256_init( &_cc );

View File

@ -43,6 +43,8 @@ class PublicKey {
PublicKey();
PublicKey(const char *pemKey);
PublicKey(const uint8_t *derKey, size_t derLen);
PublicKey(Stream& stream, size_t size);
PublicKey(Stream& stream) : PublicKey(stream, stream.available()) { };
~PublicKey();
bool parse(const char *pemKey);
@ -69,6 +71,8 @@ class PrivateKey {
PrivateKey();
PrivateKey(const char *pemKey);
PrivateKey(const uint8_t *derKey, size_t derLen);
PrivateKey(Stream& stream, size_t size);
PrivateKey(Stream& stream) : PrivateKey(stream, stream.available()) { };
~PrivateKey();
bool parse(const char *pemKey);
@ -98,6 +102,8 @@ class X509List {
X509List();
X509List(const char *pemCert);
X509List(const uint8_t *derCert, size_t derLen);
X509List(Stream& stream, size_t size);
X509List(Stream& stream) : X509List(stream, stream.available()) { };
~X509List();
bool append(const char *pemCert);
@ -127,17 +133,61 @@ class X509List {
// significantly faster. Completely optional.
class WiFiClientSecure;
// Cache for a TLS session with a server
// Use with BearSSL::WiFiClientSecure::setSession
// to accelerate the TLS handshake
class Session {
friend class WiFiClientSecure;
friend class WiFiClientSecureCtx;
public:
Session() { memset(&_session, 0, sizeof(_session)); }
private:
br_ssl_session_parameters *getSession() { return &_session; }
// The actual BearSSL ession information
// The actual BearSSL session information
br_ssl_session_parameters _session;
};
// Represents a single server session.
// Use with BearSSL::ServerSessions.
typedef uint8_t ServerSession[100];
// Cache for the TLS sessions of multiple clients.
// Use with BearSSL::WiFiServerSecure::setCache
class ServerSessions {
friend class WiFiClientSecureCtx;
public:
// Uses the given buffer to cache the given number of sessions and initializes it.
ServerSessions(ServerSession *sessions, uint32_t size) : ServerSessions(sessions, size, false) {}
// Dynamically allocates a cache for the given number of sessions and initializes it.
// If the allocation of the buffer wasn't successfull, the value
// returned by size() will be 0.
ServerSessions(uint32_t size) : ServerSessions(size > 0 ? new ServerSession[size] : nullptr, size, true) {}
~ServerSessions();
// Returns the number of sessions the cache can hold.
uint32_t size() { return _size; }
private:
ServerSessions(ServerSession *sessions, uint32_t size, bool isDynamic);
// Returns the cache's vtable or null if the cache has no capacity.
const br_ssl_session_cache_class **getCache();
// Size of the store in sessions.
uint32_t _size;
// Store where the informations for the sessions are stored.
ServerSession *_store;
// Whether the store is dynamically allocated.
// If this is true, the store needs to be freed in the destructor.
bool _isDynamic;
// Cache of the server using the _store.
br_ssl_session_cache_lru _cache;
};
// Updater SHA256 hash and signature verification
class HashSHA256 : public UpdaterHashClass {
public:
@ -164,7 +214,7 @@ class SigningVerifier : public UpdaterVerifyClass {
private:
PublicKey *_pubKey;
};
// Stack thunked versions of calls
extern "C" {
extern unsigned char *thunk_br_ssl_engine_recvapp_buf( const br_ssl_engine_context *cc, size_t *len);

View File

@ -80,7 +80,7 @@ CertStore::CertInfo CertStore::_preprocessCert(uint32_t length, uint32_t offset,
// The certs.ar file is a UNIX ar format file, concatenating all the
// individual certificates into a single blob in a space-efficient way.
int CertStore::initCertStore(FS &fs, const char *indexFileName, const char *dataFileName) {
int CertStore::initCertStore(fs::FS &fs, const char *indexFileName, const char *dataFileName) {
int count = 0;
uint32_t offset = 0;
@ -101,12 +101,12 @@ int CertStore::initCertStore(FS &fs, const char *indexFileName, const char *data
memcpy_P(_indexName, indexFileName, strlen_P(indexFileName) + 1);
memcpy_P(_dataName, dataFileName, strlen_P(dataFileName) + 1);
File index = _fs->open(_indexName, "w");
fs::File index = _fs->open(_indexName, "w");
if (!index) {
return 0;
}
File data = _fs->open(_dataName, "r");
fs::File data = _fs->open(_dataName, "r");
if (!data) {
index.close();
return 0;
@ -179,7 +179,7 @@ const br_x509_trust_anchor *CertStore::findHashedTA(void *ctx, void *hashed_dn,
return nullptr;
}
File index = cs->_fs->open(cs->_indexName, "r");
fs::File index = cs->_fs->open(cs->_indexName, "r");
if (!index) {
return nullptr;
}
@ -191,12 +191,12 @@ const br_x509_trust_anchor *CertStore::findHashedTA(void *ctx, void *hashed_dn,
if (!der) {
return nullptr;
}
File data = cs->_fs->open(cs->_dataName, "r");
fs::File data = cs->_fs->open(cs->_dataName, "r");
if (!data) {
free(der);
return nullptr;
}
if (!data.seek(ci.offset, SeekSet)) {
if (!data.seek(ci.offset, fs::SeekSet)) {
data.close();
free(der);
return nullptr;

View File

@ -31,7 +31,15 @@
namespace BearSSL {
class CertStore {
class CertStoreBase {
public:
virtual ~CertStoreBase() {}
// Installs the cert store into the X509 decoder (normally via static function callbacks)
virtual void installCertStore(br_x509_minimal_context *ctx) = 0;
};
class CertStore: public CertStoreBase {
public:
CertStore() { };
~CertStore();

View File

@ -25,7 +25,7 @@
#include <stdint.h>
extern "C" {
#include "include/wl_definitions.h"
#include <wl_definitions.h>
}
#include "IPAddress.h"

View File

@ -33,11 +33,11 @@ extern "C" {
#include "osapi.h"
#include "mem.h"
#include "user_interface.h"
#include <lwip/init.h> // LWIP_VERSION_*
}
#include "debug.h"
#include "LwipDhcpServer.h"
// -----------------------------------------------------------------------------------------------------------------------
// ---------------------------------------------------- Private functions ------------------------------------------------
@ -156,13 +156,7 @@ bool ESP8266WiFiAPClass::softAP(const char* ssid, const char* passphrase, int ch
DEBUG_WIFI("[AP] softap config unchanged\n");
}
if(wifi_softap_dhcps_status() != DHCP_STARTED) {
DEBUG_WIFI("[AP] DHCP not started, starting...\n");
if(!wifi_softap_dhcps_start()) {
DEBUG_WIFI("[AP] wifi_softap_dhcps_start failed!\n");
ret = false;
}
}
dhcpSoftAP.end();
// check IP config
struct ip_info ip;
@ -182,6 +176,8 @@ bool ESP8266WiFiAPClass::softAP(const char* ssid, const char* passphrase, int ch
ret = false;
}
dhcpSoftAP.begin(&ip);
return ret;
}
@ -237,19 +233,22 @@ bool ESP8266WiFiAPClass::softAPConfig(IPAddress local_ip, IPAddress gateway, IPA
dhcp_lease.end_ip.addr = ip.v4();
DEBUG_WIFI("[APConfig] DHCP IP end: %s\n", ip.toString().c_str());
if(!wifi_softap_set_dhcps_lease(&dhcp_lease)) {
if(!dhcpSoftAP.set_dhcps_lease(&dhcp_lease))
{
DEBUG_WIFI("[APConfig] wifi_set_ip_info failed!\n");
ret = false;
}
// set lease time to 720min --> 12h
if(!wifi_softap_set_dhcps_lease_time(720)) {
if(!dhcpSoftAP.set_dhcps_lease_time(720))
{
DEBUG_WIFI("[APConfig] wifi_softap_set_dhcps_lease_time failed!\n");
ret = false;
}
uint8 mode = info.gw.addr ? 1 : 0;
if(!wifi_softap_set_dhcps_offer_option(OFFER_ROUTER, &mode)) {
if(!dhcpSoftAP.set_dhcps_offer_option(OFFER_ROUTER, &mode))
{
DEBUG_WIFI("[APConfig] wifi_softap_set_dhcps_offer_option failed!\n");
ret = false;
}

View File

@ -1,6 +1,6 @@
/*
ESP8266WiFiGeneric.h - esp8266 Wifi support.
Based on WiFi.h from Ardiono WiFi shield library.
Based on WiFi.h from Arduino WiFi shield library.
Copyright (c) 2011-2014 Arduino. All right reserved.
Modified by Ivan Grokhotkov, December 2014
Reworked by Markus Sattler, December 2015

View File

@ -26,6 +26,7 @@
#include "ESP8266WiFiGeneric.h"
#include "ESP8266WiFiSTA.h"
#include "PolledTimeout.h"
#include "LwipIntf.h"
#include "c_types.h"
#include "ets_sys.h"
@ -281,28 +282,9 @@ bool ESP8266WiFiSTAClass::config(IPAddress local_ip, IPAddress arg1, IPAddress a
return true;
}
//To allow compatibility, check first octet of 3rd arg. If 255, interpret as ESP order, otherwise Arduino order.
IPAddress gateway = arg1;
IPAddress subnet = arg2;
IPAddress dns1 = arg3;
if(subnet[0] != 255)
{
//octet is not 255 => interpret as Arduino order
gateway = arg2;
subnet = arg3[0] == 0 ? IPAddress(255,255,255,0) : arg3; //arg order is arduino and 4th arg not given => assign it arduino default
dns1 = arg1;
}
// check whether all is IPv4 (or gateway not set)
if (!(local_ip.isV4() && subnet.isV4() && (!gateway.isSet() || gateway.isV4()))) {
IPAddress gateway, subnet, dns1;
if (!ipAddressReorder(local_ip, arg1, arg2, arg3, gateway, subnet, dns1))
return false;
}
//ip and gateway must be in the same subnet
if((local_ip.v4() & subnet.v4()) != (gateway.v4() & subnet.v4())) {
return false;
}
#if !CORE_MOCK
// get current->previous IP address
@ -522,94 +504,6 @@ IPAddress ESP8266WiFiSTAClass::dnsIP(uint8_t dns_no) {
return IPAddress(dns_getserver(dns_no));
}
/**
* Get ESP8266 station DHCP hostname
* @return hostname
*/
String ESP8266WiFiSTAClass::hostname(void) {
return wifi_station_get_hostname();
}
/**
* Set ESP8266 station DHCP hostname
* @param aHostname max length:24
* @return ok
*/
bool ESP8266WiFiSTAClass::hostname(const char* aHostname) {
/*
vvvv RFC952 vvvv
ASSUMPTIONS
1. A "name" (Net, Host, Gateway, or Domain name) is a text string up
to 24 characters drawn from the alphabet (A-Z), digits (0-9), minus
sign (-), and period (.). Note that periods are only allowed when
they serve to delimit components of "domain style names". (See
RFC-921, "Domain Name System Implementation Schedule", for
background). No blank or space characters are permitted as part of a
name. No distinction is made between upper and lower case. The first
character must be an alpha character. The last character must not be
a minus sign or period. A host which serves as a GATEWAY should have
"-GATEWAY" or "-GW" as part of its name. Hosts which do not serve as
Internet gateways should not use "-GATEWAY" and "-GW" as part of
their names. A host which is a TAC should have "-TAC" as the last
part of its host name, if it is a DoD host. Single character names
or nicknames are not allowed.
^^^^ RFC952 ^^^^
- 24 chars max
- only a..z A..Z 0..9 '-'
- no '-' as last char
*/
size_t len = strlen(aHostname);
if (len == 0 || len > 32) {
// nonos-sdk limit is 32
// (dhcp hostname option minimum size is ~60)
DEBUG_WIFI_GENERIC("WiFi.(set)hostname(): empty or large(>32) name\n");
return false;
}
// check RFC compliance
bool compliant = (len <= 24);
for (size_t i = 0; compliant && i < len; i++)
if (!isalnum(aHostname[i]) && aHostname[i] != '-')
compliant = false;
if (aHostname[len - 1] == '-')
compliant = false;
if (!compliant) {
DEBUG_WIFI_GENERIC("hostname '%s' is not compliant with RFC952\n", aHostname);
}
bool ret = wifi_station_set_hostname(aHostname);
if (!ret) {
DEBUG_WIFI_GENERIC("WiFi.hostname(%s): wifi_station_set_hostname() failed\n", aHostname);
return false;
}
// now we should inform dhcp server for this change, using lwip_renew()
// looping through all existing interface
// harmless for AP, also compatible with ethernet adapters (to come)
for (netif* intf = netif_list; intf; intf = intf->next) {
// unconditionally update all known interfaces
intf->hostname = wifi_station_get_hostname();
if (netif_dhcp_data(intf) != nullptr) {
// renew already started DHCP leases
err_t lwipret = dhcp_renew(intf);
if (lwipret != ERR_OK) {
DEBUG_WIFI_GENERIC("WiFi.hostname(%s): lwIP error %d on interface %c%c (index %d)\n",
intf->hostname, (int)lwipret, intf->name[0], intf->name[1], intf->num);
ret = false;
}
}
}
return ret && compliant;
}
/**
* Return Connection status.
* @return one of the value defined in wl_status_t

View File

@ -27,9 +27,10 @@
#include "ESP8266WiFiType.h"
#include "ESP8266WiFiGeneric.h"
#include "user_interface.h"
#include "LwipIntf.h"
class ESP8266WiFiSTAClass {
class ESP8266WiFiSTAClass: public LwipIntf {
// ----------------------------------------------------------------------------------------------
// ---------------------------------------- STA function ----------------------------------------
// ----------------------------------------------------------------------------------------------
@ -69,10 +70,6 @@ class ESP8266WiFiSTAClass {
IPAddress gatewayIP();
IPAddress dnsIP(uint8_t dns_no = 0);
String hostname();
bool hostname(const String& aHostname) { return hostname(aHostname.c_str()); }
bool hostname(const char* aHostname);
// STA WiFi info
wl_status_t status();
String SSID() const;

View File

@ -24,7 +24,7 @@
extern "C"
{
#include "include/wl_definitions.h"
#include "wl_definitions.h"
#include "osapi.h"
#include "ets_sys.h"
}
@ -195,7 +195,7 @@ bool WiFiClient::getSync() const
return _client->getSync();
}
size_t WiFiClient::availableForWrite ()
int WiFiClient::availableForWrite ()
{
return _client? _client->availableForWrite(): 0;
}

View File

@ -52,7 +52,7 @@ public:
WiFiClient(const WiFiClient&);
WiFiClient& operator=(const WiFiClient&);
uint8_t status();
virtual uint8_t status();
virtual int connect(IPAddress ip, uint16_t port) override;
virtual int connect(const char *host, uint16_t port) override;
virtual int connect(const String& host, uint16_t port);
@ -86,7 +86,7 @@ public:
static void setLocalPortStart(uint16_t port) { _localPort = port; }
size_t availableForWrite();
int availableForWrite() override;
friend class WiFiServer;

View File

@ -25,6 +25,7 @@
#include <list>
#include <errno.h>
#include <algorithm>
#include <Esp.h>
extern "C" {
#include "osapi.h"
@ -44,6 +45,9 @@ extern "C" {
#include <include/ClientContext.h>
#include "c_types.h"
#include "coredecls.h"
#include <mmu_iram.h>
#include <umm_malloc/umm_malloc.h>
#include <umm_malloc/umm_heap_select.h>
#if !CORE_MOCK
@ -67,7 +71,7 @@ extern "C" {
namespace BearSSL {
void WiFiClientSecure::_clear() {
void WiFiClientSecureCtx::_clear() {
// TLS handshake may take more than the 5 second default timeout
_timeout = 15000;
@ -91,7 +95,7 @@ void WiFiClientSecure::_clear() {
_cipher_cnt = 0;
}
void WiFiClientSecure::_clearAuthenticationSettings() {
void WiFiClientSecureCtx::_clearAuthenticationSettings() {
_use_insecure = false;
_use_fingerprint = false;
_use_self_signed = false;
@ -100,7 +104,7 @@ void WiFiClientSecure::_clearAuthenticationSettings() {
}
WiFiClientSecure::WiFiClientSecure() : WiFiClient() {
WiFiClientSecureCtx::WiFiClientSecureCtx() : WiFiClient() {
_clear();
_clearAuthenticationSettings();
_certStore = nullptr; // Don't want to remove cert store on a clear, should be long lived
@ -108,12 +112,7 @@ WiFiClientSecure::WiFiClientSecure() : WiFiClient() {
stack_thunk_add_ref();
}
WiFiClientSecure::WiFiClientSecure(const WiFiClientSecure &rhs) : WiFiClient(rhs) {
*this = rhs;
stack_thunk_add_ref();
}
WiFiClientSecure::~WiFiClientSecure() {
WiFiClientSecureCtx::~WiFiClientSecureCtx() {
if (_client) {
_client->unref();
_client = nullptr;
@ -123,9 +122,10 @@ WiFiClientSecure::~WiFiClientSecure() {
stack_thunk_del_ref();
}
WiFiClientSecure::WiFiClientSecure(ClientContext* client,
WiFiClientSecureCtx::WiFiClientSecureCtx(ClientContext* client,
const X509List *chain, const PrivateKey *sk,
int iobuf_in_size, int iobuf_out_size, const X509List *client_CA_ta) {
int iobuf_in_size, int iobuf_out_size, ServerSessions *cache,
const X509List *client_CA_ta) {
_clear();
_clearAuthenticationSettings();
stack_thunk_add_ref();
@ -133,17 +133,18 @@ WiFiClientSecure::WiFiClientSecure(ClientContext* client,
_iobuf_out_size = iobuf_out_size;
_client = client;
_client->ref();
if (!_connectSSLServerRSA(chain, sk, client_CA_ta)) {
if (!_connectSSLServerRSA(chain, sk, cache, client_CA_ta)) {
_client->unref();
_client = nullptr;
_clear();
}
}
WiFiClientSecure::WiFiClientSecure(ClientContext *client,
WiFiClientSecureCtx::WiFiClientSecureCtx(ClientContext *client,
const X509List *chain,
unsigned cert_issuer_key_type, const PrivateKey *sk,
int iobuf_in_size, int iobuf_out_size, const X509List *client_CA_ta) {
int iobuf_in_size, int iobuf_out_size, ServerSessions *cache,
const X509List *client_CA_ta) {
_clear();
_clearAuthenticationSettings();
stack_thunk_add_ref();
@ -151,19 +152,19 @@ WiFiClientSecure::WiFiClientSecure(ClientContext *client,
_iobuf_out_size = iobuf_out_size;
_client = client;
_client->ref();
if (!_connectSSLServerEC(chain, cert_issuer_key_type, sk, client_CA_ta)) {
if (!_connectSSLServerEC(chain, cert_issuer_key_type, sk, cache, client_CA_ta)) {
_client->unref();
_client = nullptr;
_clear();
}
}
void WiFiClientSecure::setClientRSACert(const X509List *chain, const PrivateKey *sk) {
void WiFiClientSecureCtx::setClientRSACert(const X509List *chain, const PrivateKey *sk) {
_chain = chain;
_sk = sk;
}
void WiFiClientSecure::setClientECCert(const X509List *chain,
void WiFiClientSecureCtx::setClientECCert(const X509List *chain,
const PrivateKey *sk, unsigned allowed_usages, unsigned cert_issuer_key_type) {
_chain = chain;
_sk = sk;
@ -171,7 +172,7 @@ void WiFiClientSecure::setClientECCert(const X509List *chain,
_cert_issuer_key_type = cert_issuer_key_type;
}
void WiFiClientSecure::setBufferSizes(int recv, int xmit) {
void WiFiClientSecureCtx::setBufferSizes(int recv, int xmit) {
// Following constants taken from bearssl/src/ssl/ssl_engine.c (not exported unfortunately)
const int MAX_OUT_OVERHEAD = 85;
const int MAX_IN_OVERHEAD = 325;
@ -187,7 +188,7 @@ void WiFiClientSecure::setBufferSizes(int recv, int xmit) {
_iobuf_out_size = xmit;
}
bool WiFiClientSecure::stop(unsigned int maxWaitMs) {
bool WiFiClientSecureCtx::stop(unsigned int maxWaitMs) {
bool ret = WiFiClient::stop(maxWaitMs); // calls our virtual flush()
// Only if we've already connected, store session params and clear the connection options
if (_handshake_done) {
@ -199,19 +200,19 @@ bool WiFiClientSecure::stop(unsigned int maxWaitMs) {
return ret;
}
bool WiFiClientSecure::flush(unsigned int maxWaitMs) {
bool WiFiClientSecureCtx::flush(unsigned int maxWaitMs) {
(void) _run_until(BR_SSL_SENDAPP);
return WiFiClient::flush(maxWaitMs);
}
int WiFiClientSecure::connect(IPAddress ip, uint16_t port) {
int WiFiClientSecureCtx::connect(IPAddress ip, uint16_t port) {
if (!WiFiClient::connect(ip, port)) {
return 0;
}
return _connectSSL(nullptr);
}
int WiFiClientSecure::connect(const char* name, uint16_t port) {
int WiFiClientSecureCtx::connect(const char* name, uint16_t port) {
IPAddress remote_addr;
if (!WiFi.hostByName(name, remote_addr)) {
DEBUG_BSSL("connect: Name lookup failure\n");
@ -224,11 +225,11 @@ int WiFiClientSecure::connect(const char* name, uint16_t port) {
return _connectSSL(name);
}
int WiFiClientSecure::connect(const String& host, uint16_t port) {
int WiFiClientSecureCtx::connect(const String& host, uint16_t port) {
return connect(host.c_str(), port);
}
void WiFiClientSecure::_freeSSL() {
void WiFiClientSecureCtx::_freeSSL() {
// These are smart pointers and will free if refcnt==0
_sc = nullptr;
_sc_svr = nullptr;
@ -245,18 +246,18 @@ void WiFiClientSecure::_freeSSL() {
_timeout = 15000;
}
bool WiFiClientSecure::_clientConnected() {
bool WiFiClientSecureCtx::_clientConnected() {
return (_client && _client->state() == ESTABLISHED);
}
uint8_t WiFiClientSecure::connected() {
uint8_t WiFiClientSecureCtx::connected() {
if (available() || (_clientConnected() && _handshake_done && (br_ssl_engine_current_state(_eng) != BR_SSL_CLOSED))) {
return true;
}
return false;
}
size_t WiFiClientSecure::_write(const uint8_t *buf, size_t size, bool pmem) {
size_t WiFiClientSecureCtx::_write(const uint8_t *buf, size_t size, bool pmem) {
size_t sent_bytes = 0;
if (!connected() || !size || !_handshake_done) {
@ -297,16 +298,16 @@ size_t WiFiClientSecure::_write(const uint8_t *buf, size_t size, bool pmem) {
return sent_bytes;
}
size_t WiFiClientSecure::write(const uint8_t *buf, size_t size) {
size_t WiFiClientSecureCtx::write(const uint8_t *buf, size_t size) {
return _write(buf, size, false);
}
size_t WiFiClientSecure::write_P(PGM_P buf, size_t size) {
size_t WiFiClientSecureCtx::write_P(PGM_P buf, size_t size) {
return _write((const uint8_t *)buf, size, true);
}
// We have to manually read and send individual chunks.
size_t WiFiClientSecure::write(Stream& stream) {
size_t WiFiClientSecureCtx::write(Stream& stream) {
size_t totalSent = 0;
size_t countRead;
size_t countSent;
@ -329,7 +330,7 @@ size_t WiFiClientSecure::write(Stream& stream) {
return totalSent;
}
int WiFiClientSecure::read(uint8_t *buf, size_t size) {
int WiFiClientSecureCtx::read(uint8_t *buf, size_t size) {
if (!ctx_present() || !_handshake_done) {
return -1;
}
@ -361,7 +362,7 @@ int WiFiClientSecure::read(uint8_t *buf, size_t size) {
return 0; // If we're connected, no error but no read.
}
int WiFiClientSecure::read() {
int WiFiClientSecureCtx::read() {
uint8_t c;
if (1 == read(&c, 1)) {
return c;
@ -370,7 +371,7 @@ int WiFiClientSecure::read() {
return -1;
}
int WiFiClientSecure::available() {
int WiFiClientSecureCtx::available() {
if (_recvapp_buf) {
return _recvapp_len; // Anything from last call?
}
@ -391,7 +392,7 @@ int WiFiClientSecure::available() {
return 0;
}
int WiFiClientSecure::peek() {
int WiFiClientSecureCtx::peek() {
if (!ctx_present() || !available()) {
DEBUG_BSSL("peek: Not connected, none left available\n");
return -1;
@ -403,7 +404,7 @@ int WiFiClientSecure::peek() {
return -1;
}
size_t WiFiClientSecure::peekBytes(uint8_t *buffer, size_t length) {
size_t WiFiClientSecureCtx::peekBytes(uint8_t *buffer, size_t length) {
size_t to_copy = 0;
if (!ctx_present()) {
DEBUG_BSSL("peekBytes: Not connected\n");
@ -426,22 +427,22 @@ size_t WiFiClientSecure::peekBytes(uint8_t *buffer, size_t length) {
combination of both (the combination matches either). When a match is
achieved, this function returns 0. On error, it returns -1.
*/
int WiFiClientSecure::_run_until(unsigned target, bool blocking) {
int WiFiClientSecureCtx::_run_until(unsigned target, bool blocking) {
if (!ctx_present()) {
DEBUG_BSSL("_run_until: Not connected\n");
return -1;
}
esp8266::polledTimeout::oneShotMs loopTimeout(_timeout);
for (int no_work = 0; blocking || no_work < 2;) {
for (int no_work = 0; blocking || no_work < 2;) {
optimistic_yield(100);
if (loopTimeout) {
DEBUG_BSSL("_run_until: Timeout\n");
return -1;
}
int state;
state = br_ssl_engine_current_state(_eng);
if (state & BR_SSL_CLOSED) {
@ -464,15 +465,15 @@ int WiFiClientSecure::_run_until(unsigned target, bool blocking) {
buf = br_ssl_engine_sendrec_buf(_eng, &len);
availForWrite = WiFiClient::availableForWrite();
if (!blocking && len > availForWrite) {
/*
/*
writes on WiFiClient will block if len > availableForWrite()
this is needed to prevent available() calls from blocking
on dropped connections
on dropped connections
*/
len = availForWrite;
}
}
wlen = WiFiClient::write(buf, len);
if (wlen <= 0) {
/*
@ -550,7 +551,7 @@ int WiFiClientSecure::_run_until(unsigned target, bool blocking) {
return -1;
}
bool WiFiClientSecure::_wait_for_handshake() {
bool WiFiClientSecureCtx::_wait_for_handshake() {
_handshake_done = false;
while (!_handshake_done && _clientConnected()) {
int ret = _run_until(BR_SSL_SENDAPP);
@ -575,7 +576,7 @@ static uint8_t htoi (unsigned char c)
}
// Set a fingerprint by parsing an ASCII string
bool WiFiClientSecure::setFingerprint(const char *fpStr) {
bool WiFiClientSecureCtx::setFingerprint(const char *fpStr) {
int idx = 0;
uint8_t c, d;
uint8_t fp[20];
@ -968,7 +969,7 @@ extern "C" {
}
// Set custom list of ciphers
bool WiFiClientSecure::setCiphers(const uint16_t *cipherAry, int cipherCount) {
bool WiFiClientSecureCtx::setCiphers(const uint16_t *cipherAry, int cipherCount) {
_cipher_list = nullptr;
_cipher_list = std::shared_ptr<uint16_t>(new (std::nothrow) uint16_t[cipherCount], std::default_delete<uint16_t[]>());
if (!_cipher_list.get()) {
@ -980,16 +981,16 @@ bool WiFiClientSecure::setCiphers(const uint16_t *cipherAry, int cipherCount) {
return true;
}
bool WiFiClientSecure::setCiphersLessSecure() {
bool WiFiClientSecureCtx::setCiphersLessSecure() {
return setCiphers(faster_suites_P, sizeof(faster_suites_P)/sizeof(faster_suites_P[0]));
}
bool WiFiClientSecure::setCiphers(std::vector<uint16_t> list) {
bool WiFiClientSecureCtx::setCiphers(const std::vector<uint16_t>& list) {
return setCiphers(&list[0], list.size());
}
// Installs the appropriate X509 cert validation method for a client connection
bool WiFiClientSecure::_installClientX509Validator() {
bool WiFiClientSecureCtx::_installClientX509Validator() {
if (_use_insecure || _use_fingerprint || _use_self_signed) {
// Use common insecure x509 authenticator
_x509_insecure = std::make_shared<struct br_x509_insecure_context>();
@ -1046,7 +1047,7 @@ bool WiFiClientSecure::_installClientX509Validator() {
// Called by connect() to do the actual SSL setup and handshake.
// Returns if the SSL handshake succeeded.
bool WiFiClientSecure::_connectSSL(const char* hostName) {
bool WiFiClientSecureCtx::_connectSSL(const char* hostName) {
DEBUG_BSSL("_connectSSL: start connection\n");
_freeSSL();
_oom_err = false;
@ -1060,8 +1061,17 @@ bool WiFiClientSecure::_connectSSL(const char* hostName) {
_sc = std::make_shared<br_ssl_client_context>();
_eng = &_sc->eng; // Allocation/deallocation taken care of by the _sc shared_ptr
_iobuf_in = std::shared_ptr<unsigned char>(new (std::nothrow) unsigned char[_iobuf_in_size], std::default_delete<unsigned char[]>());
_iobuf_out = std::shared_ptr<unsigned char>(new (std::nothrow) unsigned char[_iobuf_out_size], std::default_delete<unsigned char[]>());
//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<unsigned char>(new (std::nothrow) unsigned char[_iobuf_in_size], std::default_delete<unsigned char[]>());
_iobuf_out = std::shared_ptr<unsigned char>(new (std::nothrow) unsigned char[_iobuf_out_size], std::default_delete<unsigned char[]>());
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();
if (!_sc || !_iobuf_in || !_iobuf_out) {
_freeSSL(); // Frees _sc, _iobuf*
@ -1136,7 +1146,7 @@ bool WiFiClientSecure::_connectSSL(const char* hostName) {
// Slightly different X509 setup for servers who want to validate client
// certificates, so factor it out as it's used in RSA and EC servers.
bool WiFiClientSecure::_installServerX509Validator(const X509List *client_CA_ta) {
bool WiFiClientSecureCtx::_installServerX509Validator(const X509List *client_CA_ta) {
if (client_CA_ta) {
_ta = client_CA_ta;
// X509 minimal validator. Checks dates, cert chain for trusted CA, etc.
@ -1169,15 +1179,22 @@ bool WiFiClientSecure::_installServerX509Validator(const X509List *client_CA_ta)
// Called by WiFiServerBearSSL when an RSA cert/key is specified.
bool WiFiClientSecure::_connectSSLServerRSA(const X509List *chain,
const PrivateKey *sk,
bool WiFiClientSecureCtx::_connectSSLServerRSA(const X509List *chain,
const PrivateKey *sk, ServerSessions *cache,
const X509List *client_CA_ta) {
_freeSSL();
_oom_err = false;
_sc_svr = std::make_shared<br_ssl_server_context>();
_eng = &_sc_svr->eng; // Allocation/deallocation taken care of by the _sc shared_ptr
_iobuf_in = std::shared_ptr<unsigned char>(new (std::nothrow) unsigned char[_iobuf_in_size], std::default_delete<unsigned char[]>());
_iobuf_out = std::shared_ptr<unsigned char>(new (std::nothrow) unsigned char[_iobuf_out_size], std::default_delete<unsigned char[]>());
{ // ESP.setIramHeap();
HeapSelectIram ephemeral;
_iobuf_in = std::shared_ptr<unsigned char>(new (std::nothrow) unsigned char[_iobuf_in_size], std::default_delete<unsigned char[]>());
_iobuf_out = std::shared_ptr<unsigned char>(new (std::nothrow) unsigned char[_iobuf_out_size], std::default_delete<unsigned char[]>());
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();
if (!_sc_svr || !_iobuf_in || !_iobuf_out) {
_freeSSL();
@ -1189,8 +1206,10 @@ bool WiFiClientSecure::_connectSSLServerRSA(const X509List *chain,
br_ssl_server_base_init(_sc_svr.get(), suites_server_rsa_P, sizeof(suites_server_rsa_P) / sizeof(suites_server_rsa_P[0]));
br_ssl_server_set_single_rsa(_sc_svr.get(), chain ? chain->getX509Certs() : nullptr, chain ? chain->getCount() : 0,
sk ? sk->getRSA() : nullptr, BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN,
br_rsa_private_get_default(), br_rsa_pkcs1_sign_get_default());
br_rsa_private_get_default(), br_rsa_pkcs1_sign_get_default());
br_ssl_engine_set_buffers_bidi(_eng, _iobuf_in.get(), _iobuf_in_size, _iobuf_out.get(), _iobuf_out_size);
if (cache != nullptr)
br_ssl_server_set_cache(_sc_svr.get(), cache->getCache());
if (client_CA_ta && !_installServerX509Validator(client_CA_ta)) {
DEBUG_BSSL("_connectSSLServerRSA: Can't install serverX509check\n");
return false;
@ -1205,16 +1224,23 @@ bool WiFiClientSecure::_connectSSLServerRSA(const X509List *chain,
}
// Called by WiFiServerBearSSL when an elliptic curve cert/key is specified.
bool WiFiClientSecure::_connectSSLServerEC(const X509List *chain,
bool WiFiClientSecureCtx::_connectSSLServerEC(const X509List *chain,
unsigned cert_issuer_key_type, const PrivateKey *sk,
const X509List *client_CA_ta) {
ServerSessions *cache, const X509List *client_CA_ta) {
#ifndef BEARSSL_SSL_BASIC
_freeSSL();
_oom_err = false;
_sc_svr = std::make_shared<br_ssl_server_context>();
_eng = &_sc_svr->eng; // Allocation/deallocation taken care of by the _sc shared_ptr
_iobuf_in = std::shared_ptr<unsigned char>(new (std::nothrow) unsigned char[_iobuf_in_size], std::default_delete<unsigned char[]>());
_iobuf_out = std::shared_ptr<unsigned char>(new (std::nothrow) unsigned char[_iobuf_out_size], std::default_delete<unsigned char[]>());
{ // ESP.setIramHeap();
HeapSelectIram ephemeral;
_iobuf_in = std::shared_ptr<unsigned char>(new (std::nothrow) unsigned char[_iobuf_in_size], std::default_delete<unsigned char[]>());
_iobuf_out = std::shared_ptr<unsigned char>(new (std::nothrow) unsigned char[_iobuf_out_size], std::default_delete<unsigned char[]>());
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();
if (!_sc_svr || !_iobuf_in || !_iobuf_out) {
_freeSSL();
@ -1228,6 +1254,8 @@ bool WiFiClientSecure::_connectSSLServerEC(const X509List *chain,
sk ? sk->getEC() : nullptr, BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN,
cert_issuer_key_type, br_ssl_engine_get_ec(_eng), br_ecdsa_i15_sign_asn1);
br_ssl_engine_set_buffers_bidi(_eng, _iobuf_in.get(), _iobuf_in_size, _iobuf_out.get(), _iobuf_out_size);
if (cache != nullptr)
br_ssl_server_set_cache(_sc_svr.get(), cache->getCache());
if (client_CA_ta && !_installServerX509Validator(client_CA_ta)) {
DEBUG_BSSL("_connectSSLServerEC: Can't install serverX509check\n");
return false;
@ -1251,14 +1279,25 @@ bool WiFiClientSecure::_connectSSLServerEC(const X509List *chain,
// Returns an error ID and possibly a string (if dest != null) of the last
// BearSSL reported error.
int WiFiClientSecure::getLastSSLError(char *dest, size_t len) {
int WiFiClientSecureCtx::getLastSSLError(char *dest, size_t len) {
int err = 0;
const char *t = PSTR("OK");
const char *recv_fatal = "";
const char *send_fatal = "";
if (_sc || _sc_svr) {
err = br_ssl_engine_last_error(_eng);
}
if (_oom_err) {
err = -1000;
} else {
if (err & BR_ERR_RECV_FATAL_ALERT) {
recv_fatal = PSTR("SSL received fatal alert - ");
err &= ~BR_ERR_RECV_FATAL_ALERT;
}
if (err & BR_ERR_SEND_FATAL_ALERT) {
send_fatal = PSTR("SSL sent fatal alert - ");
err &= ~BR_ERR_SEND_FATAL_ALERT;
}
}
switch (err) {
case -1000: t = PSTR("Unable to allocate memory for SSL structures and buffers."); break;
@ -1323,8 +1362,8 @@ int WiFiClientSecure::getLastSSLError(char *dest, size_t len) {
default: t = PSTR("Unknown error code."); break;
}
if (dest) {
strncpy_P(dest, t, len);
dest[len - 1] = 0;
// snprintf is PSTR safe and guaranteed to 0-terminate
snprintf(dest, len, "%s%s%s", recv_fatal, send_fatal, t);
}
return err;
}
@ -1395,7 +1434,7 @@ bool WiFiClientSecure::probeMaxFragmentLength(IPAddress ip, uint16_t port, uint1
0x00, 26 + 14 + 6 + 5, // Extension length
0x00, 0x0d, 0x00, 0x16, 0x00, 0x14, 0x04, 0x03, 0x03, 0x03, 0x05, 0x03,
0x06, 0x03, 0x02, 0x03, 0x04, 0x01, 0x03, 0x01, 0x05, 0x01, 0x06,
0x01, 0x02, 0x01, // Supported signature algorithms
0x01, 0x02, 0x01, // Supported signature algorithms
0x00, 0x0a, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19,
0x00, 0x1d, // Supported groups
0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, // Supported EC formats

View File

@ -31,13 +31,13 @@
namespace BearSSL {
class WiFiClientSecure : public WiFiClient {
class WiFiClientSecureCtx : public WiFiClient {
public:
WiFiClientSecure();
WiFiClientSecure(const WiFiClientSecure &rhs);
~WiFiClientSecure() override;
WiFiClientSecureCtx();
WiFiClientSecureCtx(const WiFiClientSecure &rhs) = delete;
~WiFiClientSecureCtx() override;
WiFiClientSecure& operator=(const WiFiClientSecure&) = default; // The shared-ptrs handle themselves automatically
WiFiClientSecureCtx& operator=(const WiFiClientSecureCtx&) = delete;
int connect(IPAddress ip, uint16_t port) override;
int connect(const String& host, uint16_t port) override;
@ -46,12 +46,6 @@ class WiFiClientSecure : public WiFiClient {
uint8_t connected() override;
size_t write(const uint8_t *buf, size_t size) override;
size_t write_P(PGM_P buf, size_t size) override;
size_t write(const char *buf) {
return write((const uint8_t*)buf, strlen(buf));
}
size_t write_P(const char *buf) {
return write_P((PGM_P)buf, strlen_P(buf));
}
size_t write(Stream& stream); // Note this is not virtual
int read(uint8_t *buf, size_t size) override;
int available() override;
@ -116,21 +110,16 @@ class WiFiClientSecure : public WiFiClient {
int getLastSSLError(char *dest = NULL, size_t len = 0);
// Attach a preconfigured certificate store
void setCertStore(CertStore *certStore) {
void setCertStore(CertStoreBase *certStore) {
_certStore = certStore;
}
// Select specific ciphers (i.e. optimize for speed over security)
// These may be in PROGMEM or RAM, either will run properly
bool setCiphers(const uint16_t *cipherAry, int cipherCount);
bool setCiphers(std::vector<uint16_t> list);
bool setCiphers(const std::vector<uint16_t>& list);
bool setCiphersLessSecure(); // Only use the limited set of RSA ciphers without EC
// 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);
static bool probeMaxFragmentLength(const String& host, uint16_t port, uint16_t len);
protected:
bool _connectSSL(const char *hostName); // Do initial SSL handshake
@ -151,7 +140,7 @@ class WiFiClientSecure : public WiFiClient {
std::shared_ptr<unsigned char> _iobuf_out;
time_t _now;
const X509List *_ta;
CertStore *_certStore;
CertStoreBase *_certStore;
int _iobuf_in_size;
int _iobuf_out_size;
bool _handshake_done;
@ -188,25 +177,135 @@ class WiFiClientSecure : public WiFiClient {
unsigned _cert_issuer_key_type;
// Methods for handling server.available() call which returns a client connection.
friend class WiFiServerSecure; // Server needs to access these constructors
WiFiClientSecure(ClientContext *client, const X509List *chain, unsigned cert_issuer_key_type,
const PrivateKey *sk, int iobuf_in_size, int iobuf_out_size, const X509List *client_CA_ta);
WiFiClientSecure(ClientContext* client, const X509List *chain, const PrivateKey *sk,
int iobuf_in_size, int iobuf_out_size, const X509List *client_CA_ta);
friend class WiFiClientSecure; // access to private context constructors
WiFiClientSecureCtx(ClientContext *client, const X509List *chain, unsigned cert_issuer_key_type,
const PrivateKey *sk, int iobuf_in_size, int iobuf_out_size, ServerSessions *cache,
const X509List *client_CA_ta);
WiFiClientSecureCtx(ClientContext* client, const X509List *chain, const PrivateKey *sk,
int iobuf_in_size, int iobuf_out_size, ServerSessions *cache,
const X509List *client_CA_ta);
// RSA keyed server
bool _connectSSLServerRSA(const X509List *chain, const PrivateKey *sk, const X509List *client_CA_ta);
bool _connectSSLServerRSA(const X509List *chain, const PrivateKey *sk,
ServerSessions *cache, const X509List *client_CA_ta);
// EC keyed server
bool _connectSSLServerEC(const X509List *chain, unsigned cert_issuer_key_type, const PrivateKey *sk,
const X509List *client_CA_ta);
ServerSessions *cache, const X509List *client_CA_ta);
// X.509 validators differ from server to client
bool _installClientX509Validator(); // Set up X509 validator for a client conn.
bool _installServerX509Validator(const X509List *client_CA_ta); // Setup X509 client cert validation, if supplied
uint8_t *_streamLoad(Stream& stream, size_t size);
};
}; // class WiFiClientSecureCtx
};
class WiFiClientSecure : public WiFiClient {
// WiFiClient's "ClientContext* _client" is always nullptr in this class.
// Instead, all virtual functions call their counterpart in "WiFiClientecureCtx* _ctx"
// which also derives from WiFiClient (this parent is the one which is eventually used)
public:
WiFiClientSecure():_ctx(new WiFiClientSecureCtx()) { }
WiFiClientSecure(const WiFiClientSecure &rhs): WiFiClient(), _ctx(rhs._ctx) { }
~WiFiClientSecure() override { _ctx = nullptr; }
WiFiClientSecure& operator=(const WiFiClientSecure&) = default; // The shared-ptrs handle themselves automatically
uint8_t status() override { return _ctx->status(); }
int connect(IPAddress ip, uint16_t port) override { return _ctx->connect(ip, port); }
int connect(const String& host, uint16_t port) override { return _ctx->connect(host, port); }
int connect(const char* name, uint16_t port) override { return _ctx->connect(name, port); }
uint8_t connected() override { return _ctx->connected(); }
size_t write(const uint8_t *buf, size_t size) override { return _ctx->write(buf, size); }
size_t write_P(PGM_P buf, size_t size) override { return _ctx->write_P(buf, size); }
size_t write(const char *buf) { return write((const uint8_t*)buf, strlen(buf)); }
size_t write_P(const char *buf) { return write_P((PGM_P)buf, strlen_P(buf)); }
size_t write(Stream& stream) /* Note this is not virtual */ { return _ctx->write(stream); }
int read(uint8_t *buf, size_t size) override { return _ctx->read(buf, size); }
int available() override { return _ctx->available(); }
int read() override { return _ctx->read(); }
int peek() override { return _ctx->peek(); }
size_t peekBytes(uint8_t *buffer, size_t length) override { return _ctx->peekBytes(buffer, length); }
bool flush(unsigned int maxWaitMs) { return _ctx->flush(maxWaitMs); }
bool stop(unsigned int maxWaitMs) { return _ctx->stop(maxWaitMs); }
void flush() override { (void)flush(0); }
void stop() override { (void)stop(0); }
// Allow sessions to be saved/restored automatically to a memory area
void setSession(Session *session) { _ctx->setSession(session); }
// Don't validate the chain, just accept whatever is given. VERY INSECURE!
void setInsecure() { _ctx->setInsecure(); }
// Assume a given public key, don't validate or use cert info at all
void setKnownKey(const PublicKey *pk, unsigned usages = BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN) {
_ctx->setKnownKey(pk, usages);
}
// Only check SHA1 fingerprint of certificate
bool setFingerprint(const uint8_t fingerprint[20]) {
return _ctx->setFingerprint(fingerprint);
}
bool setFingerprint(const char *fpStr) { return _ctx->setFingerprint(fpStr); }
// Accept any certificate that's self-signed
void allowSelfSignedCerts() { _ctx->allowSelfSignedCerts(); }
// Install certificates of trusted CAs or specific site
void setTrustAnchors(const X509List *ta) { _ctx->setTrustAnchors(ta); }
// In cases when NTP is not used, app must set a time manually to check cert validity
void setX509Time(time_t now) { _ctx->setX509Time(now); }
// Install a client certificate for this connection, in case the server requires it (i.e. MQTT)
void setClientRSACert(const X509List *cert, const PrivateKey *sk) { _ctx->setClientRSACert(cert, sk); }
void setClientECCert(const X509List *cert, const PrivateKey *sk,
unsigned allowed_usages, unsigned cert_issuer_key_type) {
_ctx->setClientECCert(cert, sk, allowed_usages, cert_issuer_key_type);
}
// Sets the requested buffer size for transmit and receive
void setBufferSizes(int recv, int xmit) { _ctx->setBufferSizes(recv, xmit); }
// Returns whether MFLN negotiation for the above buffer sizes succeeded (after connection)
int getMFLNStatus() { return _ctx->getMFLNStatus(); }
// Return an error code and possibly a text string in a passed-in buffer with last SSL failure
int getLastSSLError(char *dest = NULL, size_t len = 0) { return _ctx->getLastSSLError(dest, len); }
// Attach a preconfigured certificate store
void setCertStore(CertStoreBase *certStore) { _ctx->setCertStore(certStore); }
// Select specific ciphers (i.e. optimize for speed over security)
// These may be in PROGMEM or RAM, either will run properly
bool setCiphers(const uint16_t *cipherAry, int cipherCount) { return _ctx->setCiphers(cipherAry, cipherCount); }
bool setCiphers(const std::vector<uint16_t> list) { return _ctx->setCiphers(list); }
bool setCiphersLessSecure() { return _ctx->setCiphersLessSecure(); } // Only use the limited set of RSA ciphers without EC
// 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);
static bool probeMaxFragmentLength(const String& host, uint16_t port, uint16_t len);
private:
std::shared_ptr<WiFiClientSecureCtx> _ctx;
// Methods for handling server.available() call which returns a client connection.
friend class WiFiServerSecure; // Server needs to access these constructors
WiFiClientSecure(ClientContext *client, const X509List *chain, unsigned cert_issuer_key_type,
const PrivateKey *sk, int iobuf_in_size, int iobuf_out_size, ServerSessions *cache,
const X509List *client_CA_ta):
_ctx(new WiFiClientSecureCtx(client, chain, cert_issuer_key_type, sk, iobuf_in_size, iobuf_out_size, cache, client_CA_ta)) {
}
WiFiClientSecure(ClientContext* client, const X509List *chain, const PrivateKey *sk,
int iobuf_in_size, int iobuf_out_size, ServerSessions *cache,
const X509List *client_CA_ta):
_ctx(new WiFiClientSecureCtx(client, chain, sk, iobuf_in_size, iobuf_out_size, cache, client_CA_ta)) {
}
}; // class WiFiClientSecure
}; // namespace BearSSL
#endif

View File

@ -115,9 +115,10 @@ WiFiClient WiFiServer::available(byte* status) {
WiFiClient result(_unclaimed);
// pcb can be null when peer has already closed the connection
if (_unclaimed->getPCB())
if (_unclaimed->getPCB()) {
// give permission to lwIP to accept one more peer
tcp_backlog_accepted(_unclaimed->getPCB());
}
_unclaimed = _unclaimed->next();
result.setNoDelay(getNoDelay());

View File

@ -23,7 +23,7 @@
#define wifiserver_h
extern "C" {
#include "include/wl_definitions.h"
#include "wl_definitions.h"
struct tcp_pcb;
}

View File

@ -79,13 +79,13 @@ 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);
WiFiClientSecure result(_unclaimed, _chain, _sk, _iobuf_in_size, _iobuf_out_size, _cache, _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);
WiFiClientSecure result(_unclaimed, _chain, _cert_issuer_key_type, _sk, _iobuf_in_size, _iobuf_out_size, _cache, _client_CA_ta);
_unclaimed = _unclaimed->next();
result.setNoDelay(_noDelay);
DEBUGV("WS:av\r\n");

View File

@ -42,6 +42,11 @@ class WiFiServerSecure : public WiFiServer {
_iobuf_out_size = xmit;
}
// Sets the server's cache to the given one.
void setCache(ServerSessions *cache) {
_cache = cache;
}
// Set the server's RSA key and x509 certificate (required, pick one).
// Caller needs to preserve the chain and key throughout the life of the server.
void setRSACert(const X509List *chain, const PrivateKey *sk);
@ -69,6 +74,7 @@ class WiFiServerSecure : public WiFiServer {
int _iobuf_in_size = BR_SSL_BUFSIZE_INPUT;
int _iobuf_out_size = 837;
const X509List *_client_CA_ta = nullptr;
ServerSessions *_cache = nullptr;
};

View File

@ -25,7 +25,7 @@
extern "C"
{
#include "include/wl_definitions.h"
#include "wl_definitions.h"
#include "osapi.h"
#include "ets_sys.h"
}

View File

@ -1,88 +0,0 @@
/*
wl_definitions.h - Library for Arduino Wifi shield.
Copyright (c) 2011-2014 Arduino. All right reserved.
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
*/
/*
* wl_definitions.h
*
* Created on: Mar 6, 2011
* Author: dlafauci
*/
#ifndef WL_DEFINITIONS_H_
#define WL_DEFINITIONS_H_
// Maximum size of a SSID
#define WL_SSID_MAX_LENGTH 32
// Length of passphrase. Valid lengths are 8-63.
#define WL_WPA_KEY_MAX_LENGTH 63
// Length of key in bytes. Valid values are 5 and 13.
#define WL_WEP_KEY_MAX_LENGTH 13
// Size of a MAC-address or BSSID
#define WL_MAC_ADDR_LENGTH 6
// Size of a MAC-address or BSSID
#define WL_IPV4_LENGTH 4
// Maximum size of a SSID list
#define WL_NETWORKS_LIST_MAXNUM 10
// Maxmium number of socket
#define MAX_SOCK_NUM 4
// Socket not available constant
#define SOCK_NOT_AVAIL 255
// Default state value for Wifi state field
#define NA_STATE -1
//Maximum number of attempts to establish wifi connection
#define WL_MAX_ATTEMPT_CONNECTION 10
typedef enum {
WL_NO_SHIELD = 255, // for compatibility with WiFi Shield library
WL_IDLE_STATUS = 0,
WL_NO_SSID_AVAIL = 1,
WL_SCAN_COMPLETED = 2,
WL_CONNECTED = 3,
WL_CONNECT_FAILED = 4,
WL_CONNECTION_LOST = 5,
WL_WRONG_PASSWORD = 6,
WL_DISCONNECTED = 7
} wl_status_t;
/* Encryption modes */
enum wl_enc_type { /* Values map to 802.11 encryption suites... */
ENC_TYPE_WEP = 5,
ENC_TYPE_TKIP = 2,
ENC_TYPE_CCMP = 4,
/* ... except these two, 7 and 8 are reserved in 802.11-2007 */
ENC_TYPE_NONE = 7,
ENC_TYPE_AUTO = 8
};
#if !defined(LWIP_INTERNAL) && !defined(__LWIP_TCP_H__)
enum wl_tcp_state {
CLOSED = 0,
LISTEN = 1,
SYN_SENT = 2,
SYN_RCVD = 3,
ESTABLISHED = 4,
FIN_WAIT_1 = 5,
FIN_WAIT_2 = 6,
CLOSE_WAIT = 7,
CLOSING = 8,
LAST_ACK = 9,
TIME_WAIT = 10
};
#endif
#endif /* WL_DEFINITIONS_H_ */