mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-19 23:22:16 +03:00
WiFiClientSecure: use context (#7680)
* move WiFiClientSecure to WiFiClientSecureCtx and add WiFiClientSecure wrapper to handle the context * explicitely disable context copy constructor (similar to operator=) * move (static) probeMaxFragmentLength back from ctx to WiFiClientSecure * route sslclient::status() to context's ::status()
This commit is contained in:
parent
35a5a7026c
commit
594831d605
@ -134,7 +134,7 @@ class X509List {
|
|||||||
class WiFiClientSecure;
|
class WiFiClientSecure;
|
||||||
|
|
||||||
class Session {
|
class Session {
|
||||||
friend class WiFiClientSecure;
|
friend class WiFiClientSecureCtx;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Session() { memset(&_session, 0, sizeof(_session)); }
|
Session() { memset(&_session, 0, sizeof(_session)); }
|
||||||
|
@ -52,7 +52,7 @@ public:
|
|||||||
WiFiClient(const WiFiClient&);
|
WiFiClient(const WiFiClient&);
|
||||||
WiFiClient& operator=(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(IPAddress ip, uint16_t port) override;
|
||||||
virtual int connect(const char *host, uint16_t port) override;
|
virtual int connect(const char *host, uint16_t port) override;
|
||||||
virtual int connect(const String& host, uint16_t port);
|
virtual int connect(const String& host, uint16_t port);
|
||||||
|
@ -67,7 +67,7 @@ extern "C" {
|
|||||||
|
|
||||||
namespace BearSSL {
|
namespace BearSSL {
|
||||||
|
|
||||||
void WiFiClientSecure::_clear() {
|
void WiFiClientSecureCtx::_clear() {
|
||||||
// TLS handshake may take more than the 5 second default timeout
|
// TLS handshake may take more than the 5 second default timeout
|
||||||
_timeout = 15000;
|
_timeout = 15000;
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ void WiFiClientSecure::_clear() {
|
|||||||
_cipher_cnt = 0;
|
_cipher_cnt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WiFiClientSecure::_clearAuthenticationSettings() {
|
void WiFiClientSecureCtx::_clearAuthenticationSettings() {
|
||||||
_use_insecure = false;
|
_use_insecure = false;
|
||||||
_use_fingerprint = false;
|
_use_fingerprint = false;
|
||||||
_use_self_signed = false;
|
_use_self_signed = false;
|
||||||
@ -100,7 +100,7 @@ void WiFiClientSecure::_clearAuthenticationSettings() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
WiFiClientSecure::WiFiClientSecure() : WiFiClient() {
|
WiFiClientSecureCtx::WiFiClientSecureCtx() : WiFiClient() {
|
||||||
_clear();
|
_clear();
|
||||||
_clearAuthenticationSettings();
|
_clearAuthenticationSettings();
|
||||||
_certStore = nullptr; // Don't want to remove cert store on a clear, should be long lived
|
_certStore = nullptr; // Don't want to remove cert store on a clear, should be long lived
|
||||||
@ -108,12 +108,7 @@ WiFiClientSecure::WiFiClientSecure() : WiFiClient() {
|
|||||||
stack_thunk_add_ref();
|
stack_thunk_add_ref();
|
||||||
}
|
}
|
||||||
|
|
||||||
WiFiClientSecure::WiFiClientSecure(const WiFiClientSecure &rhs) : WiFiClient(rhs) {
|
WiFiClientSecureCtx::~WiFiClientSecureCtx() {
|
||||||
*this = rhs;
|
|
||||||
stack_thunk_add_ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
WiFiClientSecure::~WiFiClientSecure() {
|
|
||||||
if (_client) {
|
if (_client) {
|
||||||
_client->unref();
|
_client->unref();
|
||||||
_client = nullptr;
|
_client = nullptr;
|
||||||
@ -123,7 +118,7 @@ WiFiClientSecure::~WiFiClientSecure() {
|
|||||||
stack_thunk_del_ref();
|
stack_thunk_del_ref();
|
||||||
}
|
}
|
||||||
|
|
||||||
WiFiClientSecure::WiFiClientSecure(ClientContext* client,
|
WiFiClientSecureCtx::WiFiClientSecureCtx(ClientContext* client,
|
||||||
const X509List *chain, const PrivateKey *sk,
|
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, const X509List *client_CA_ta) {
|
||||||
_clear();
|
_clear();
|
||||||
@ -140,7 +135,7 @@ WiFiClientSecure::WiFiClientSecure(ClientContext* client,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WiFiClientSecure::WiFiClientSecure(ClientContext *client,
|
WiFiClientSecureCtx::WiFiClientSecureCtx(ClientContext *client,
|
||||||
const X509List *chain,
|
const X509List *chain,
|
||||||
unsigned cert_issuer_key_type, const PrivateKey *sk,
|
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, const X509List *client_CA_ta) {
|
||||||
@ -158,12 +153,12 @@ WiFiClientSecure::WiFiClientSecure(ClientContext *client,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WiFiClientSecure::setClientRSACert(const X509List *chain, const PrivateKey *sk) {
|
void WiFiClientSecureCtx::setClientRSACert(const X509List *chain, const PrivateKey *sk) {
|
||||||
_chain = chain;
|
_chain = chain;
|
||||||
_sk = sk;
|
_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) {
|
const PrivateKey *sk, unsigned allowed_usages, unsigned cert_issuer_key_type) {
|
||||||
_chain = chain;
|
_chain = chain;
|
||||||
_sk = sk;
|
_sk = sk;
|
||||||
@ -171,7 +166,7 @@ void WiFiClientSecure::setClientECCert(const X509List *chain,
|
|||||||
_cert_issuer_key_type = cert_issuer_key_type;
|
_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)
|
// Following constants taken from bearssl/src/ssl/ssl_engine.c (not exported unfortunately)
|
||||||
const int MAX_OUT_OVERHEAD = 85;
|
const int MAX_OUT_OVERHEAD = 85;
|
||||||
const int MAX_IN_OVERHEAD = 325;
|
const int MAX_IN_OVERHEAD = 325;
|
||||||
@ -187,7 +182,7 @@ void WiFiClientSecure::setBufferSizes(int recv, int xmit) {
|
|||||||
_iobuf_out_size = 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()
|
bool ret = WiFiClient::stop(maxWaitMs); // calls our virtual flush()
|
||||||
// Only if we've already connected, store session params and clear the connection options
|
// Only if we've already connected, store session params and clear the connection options
|
||||||
if (_handshake_done) {
|
if (_handshake_done) {
|
||||||
@ -199,19 +194,19 @@ bool WiFiClientSecure::stop(unsigned int maxWaitMs) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WiFiClientSecure::flush(unsigned int maxWaitMs) {
|
bool WiFiClientSecureCtx::flush(unsigned int maxWaitMs) {
|
||||||
(void) _run_until(BR_SSL_SENDAPP);
|
(void) _run_until(BR_SSL_SENDAPP);
|
||||||
return WiFiClient::flush(maxWaitMs);
|
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)) {
|
if (!WiFiClient::connect(ip, port)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return _connectSSL(nullptr);
|
return _connectSSL(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int WiFiClientSecure::connect(const char* name, uint16_t port) {
|
int WiFiClientSecureCtx::connect(const char* name, uint16_t port) {
|
||||||
IPAddress remote_addr;
|
IPAddress remote_addr;
|
||||||
if (!WiFi.hostByName(name, remote_addr)) {
|
if (!WiFi.hostByName(name, remote_addr)) {
|
||||||
DEBUG_BSSL("connect: Name lookup failure\n");
|
DEBUG_BSSL("connect: Name lookup failure\n");
|
||||||
@ -224,11 +219,11 @@ int WiFiClientSecure::connect(const char* name, uint16_t port) {
|
|||||||
return _connectSSL(name);
|
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);
|
return connect(host.c_str(), port);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WiFiClientSecure::_freeSSL() {
|
void WiFiClientSecureCtx::_freeSSL() {
|
||||||
// These are smart pointers and will free if refcnt==0
|
// These are smart pointers and will free if refcnt==0
|
||||||
_sc = nullptr;
|
_sc = nullptr;
|
||||||
_sc_svr = nullptr;
|
_sc_svr = nullptr;
|
||||||
@ -245,18 +240,18 @@ void WiFiClientSecure::_freeSSL() {
|
|||||||
_timeout = 15000;
|
_timeout = 15000;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WiFiClientSecure::_clientConnected() {
|
bool WiFiClientSecureCtx::_clientConnected() {
|
||||||
return (_client && _client->state() == ESTABLISHED);
|
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))) {
|
if (available() || (_clientConnected() && _handshake_done && (br_ssl_engine_current_state(_eng) != BR_SSL_CLOSED))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
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;
|
size_t sent_bytes = 0;
|
||||||
|
|
||||||
if (!connected() || !size || !_handshake_done) {
|
if (!connected() || !size || !_handshake_done) {
|
||||||
@ -297,16 +292,16 @@ size_t WiFiClientSecure::_write(const uint8_t *buf, size_t size, bool pmem) {
|
|||||||
return sent_bytes;
|
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);
|
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);
|
return _write((const uint8_t *)buf, size, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have to manually read and send individual chunks.
|
// 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 totalSent = 0;
|
||||||
size_t countRead;
|
size_t countRead;
|
||||||
size_t countSent;
|
size_t countSent;
|
||||||
@ -329,7 +324,7 @@ size_t WiFiClientSecure::write(Stream& stream) {
|
|||||||
return totalSent;
|
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) {
|
if (!ctx_present() || !_handshake_done) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -361,7 +356,7 @@ int WiFiClientSecure::read(uint8_t *buf, size_t size) {
|
|||||||
return 0; // If we're connected, no error but no read.
|
return 0; // If we're connected, no error but no read.
|
||||||
}
|
}
|
||||||
|
|
||||||
int WiFiClientSecure::read() {
|
int WiFiClientSecureCtx::read() {
|
||||||
uint8_t c;
|
uint8_t c;
|
||||||
if (1 == read(&c, 1)) {
|
if (1 == read(&c, 1)) {
|
||||||
return c;
|
return c;
|
||||||
@ -370,7 +365,7 @@ int WiFiClientSecure::read() {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WiFiClientSecure::available() {
|
int WiFiClientSecureCtx::available() {
|
||||||
if (_recvapp_buf) {
|
if (_recvapp_buf) {
|
||||||
return _recvapp_len; // Anything from last call?
|
return _recvapp_len; // Anything from last call?
|
||||||
}
|
}
|
||||||
@ -391,7 +386,7 @@ int WiFiClientSecure::available() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WiFiClientSecure::peek() {
|
int WiFiClientSecureCtx::peek() {
|
||||||
if (!ctx_present() || !available()) {
|
if (!ctx_present() || !available()) {
|
||||||
DEBUG_BSSL("peek: Not connected, none left available\n");
|
DEBUG_BSSL("peek: Not connected, none left available\n");
|
||||||
return -1;
|
return -1;
|
||||||
@ -403,7 +398,7 @@ int WiFiClientSecure::peek() {
|
|||||||
return -1;
|
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;
|
size_t to_copy = 0;
|
||||||
if (!ctx_present()) {
|
if (!ctx_present()) {
|
||||||
DEBUG_BSSL("peekBytes: Not connected\n");
|
DEBUG_BSSL("peekBytes: Not connected\n");
|
||||||
@ -426,7 +421,7 @@ size_t WiFiClientSecure::peekBytes(uint8_t *buffer, size_t length) {
|
|||||||
combination of both (the combination matches either). When a match is
|
combination of both (the combination matches either). When a match is
|
||||||
achieved, this function returns 0. On error, it returns -1.
|
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()) {
|
if (!ctx_present()) {
|
||||||
DEBUG_BSSL("_run_until: Not connected\n");
|
DEBUG_BSSL("_run_until: Not connected\n");
|
||||||
return -1;
|
return -1;
|
||||||
@ -550,7 +545,7 @@ int WiFiClientSecure::_run_until(unsigned target, bool blocking) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WiFiClientSecure::_wait_for_handshake() {
|
bool WiFiClientSecureCtx::_wait_for_handshake() {
|
||||||
_handshake_done = false;
|
_handshake_done = false;
|
||||||
while (!_handshake_done && _clientConnected()) {
|
while (!_handshake_done && _clientConnected()) {
|
||||||
int ret = _run_until(BR_SSL_SENDAPP);
|
int ret = _run_until(BR_SSL_SENDAPP);
|
||||||
@ -575,7 +570,7 @@ static uint8_t htoi (unsigned char c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set a fingerprint by parsing an ASCII string
|
// Set a fingerprint by parsing an ASCII string
|
||||||
bool WiFiClientSecure::setFingerprint(const char *fpStr) {
|
bool WiFiClientSecureCtx::setFingerprint(const char *fpStr) {
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
uint8_t c, d;
|
uint8_t c, d;
|
||||||
uint8_t fp[20];
|
uint8_t fp[20];
|
||||||
@ -968,7 +963,7 @@ extern "C" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set custom list of ciphers
|
// 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 = nullptr;
|
||||||
_cipher_list = std::shared_ptr<uint16_t>(new (std::nothrow) uint16_t[cipherCount], std::default_delete<uint16_t[]>());
|
_cipher_list = std::shared_ptr<uint16_t>(new (std::nothrow) uint16_t[cipherCount], std::default_delete<uint16_t[]>());
|
||||||
if (!_cipher_list.get()) {
|
if (!_cipher_list.get()) {
|
||||||
@ -980,16 +975,16 @@ bool WiFiClientSecure::setCiphers(const uint16_t *cipherAry, int cipherCount) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WiFiClientSecure::setCiphersLessSecure() {
|
bool WiFiClientSecureCtx::setCiphersLessSecure() {
|
||||||
return setCiphers(faster_suites_P, sizeof(faster_suites_P)/sizeof(faster_suites_P[0]));
|
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());
|
return setCiphers(&list[0], list.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Installs the appropriate X509 cert validation method for a client connection
|
// 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) {
|
if (_use_insecure || _use_fingerprint || _use_self_signed) {
|
||||||
// Use common insecure x509 authenticator
|
// Use common insecure x509 authenticator
|
||||||
_x509_insecure = std::make_shared<struct br_x509_insecure_context>();
|
_x509_insecure = std::make_shared<struct br_x509_insecure_context>();
|
||||||
@ -1046,7 +1041,7 @@ bool WiFiClientSecure::_installClientX509Validator() {
|
|||||||
|
|
||||||
// Called by connect() to do the actual SSL setup and handshake.
|
// Called by connect() to do the actual SSL setup and handshake.
|
||||||
// Returns if the SSL handshake succeeded.
|
// Returns if the SSL handshake succeeded.
|
||||||
bool WiFiClientSecure::_connectSSL(const char* hostName) {
|
bool WiFiClientSecureCtx::_connectSSL(const char* hostName) {
|
||||||
DEBUG_BSSL("_connectSSL: start connection\n");
|
DEBUG_BSSL("_connectSSL: start connection\n");
|
||||||
_freeSSL();
|
_freeSSL();
|
||||||
_oom_err = false;
|
_oom_err = false;
|
||||||
@ -1136,7 +1131,7 @@ bool WiFiClientSecure::_connectSSL(const char* hostName) {
|
|||||||
|
|
||||||
// Slightly different X509 setup for servers who want to validate client
|
// 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.
|
// 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) {
|
if (client_CA_ta) {
|
||||||
_ta = client_CA_ta;
|
_ta = client_CA_ta;
|
||||||
// X509 minimal validator. Checks dates, cert chain for trusted CA, etc.
|
// X509 minimal validator. Checks dates, cert chain for trusted CA, etc.
|
||||||
@ -1169,7 +1164,7 @@ bool WiFiClientSecure::_installServerX509Validator(const X509List *client_CA_ta)
|
|||||||
|
|
||||||
|
|
||||||
// Called by WiFiServerBearSSL when an RSA cert/key is specified.
|
// Called by WiFiServerBearSSL when an RSA cert/key is specified.
|
||||||
bool WiFiClientSecure::_connectSSLServerRSA(const X509List *chain,
|
bool WiFiClientSecureCtx::_connectSSLServerRSA(const X509List *chain,
|
||||||
const PrivateKey *sk,
|
const PrivateKey *sk,
|
||||||
const X509List *client_CA_ta) {
|
const X509List *client_CA_ta) {
|
||||||
_freeSSL();
|
_freeSSL();
|
||||||
@ -1205,7 +1200,7 @@ bool WiFiClientSecure::_connectSSLServerRSA(const X509List *chain,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Called by WiFiServerBearSSL when an elliptic curve cert/key is specified.
|
// 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,
|
unsigned cert_issuer_key_type, const PrivateKey *sk,
|
||||||
const X509List *client_CA_ta) {
|
const X509List *client_CA_ta) {
|
||||||
#ifndef BEARSSL_SSL_BASIC
|
#ifndef BEARSSL_SSL_BASIC
|
||||||
@ -1251,7 +1246,7 @@ bool WiFiClientSecure::_connectSSLServerEC(const X509List *chain,
|
|||||||
|
|
||||||
// Returns an error ID and possibly a string (if dest != null) of the last
|
// Returns an error ID and possibly a string (if dest != null) of the last
|
||||||
// BearSSL reported error.
|
// BearSSL reported error.
|
||||||
int WiFiClientSecure::getLastSSLError(char *dest, size_t len) {
|
int WiFiClientSecureCtx::getLastSSLError(char *dest, size_t len) {
|
||||||
int err = 0;
|
int err = 0;
|
||||||
const char *t = PSTR("OK");
|
const char *t = PSTR("OK");
|
||||||
const char *recv_fatal = "";
|
const char *recv_fatal = "";
|
||||||
|
@ -31,13 +31,13 @@
|
|||||||
|
|
||||||
namespace BearSSL {
|
namespace BearSSL {
|
||||||
|
|
||||||
class WiFiClientSecure : public WiFiClient {
|
class WiFiClientSecureCtx : public WiFiClient {
|
||||||
public:
|
public:
|
||||||
WiFiClientSecure();
|
WiFiClientSecureCtx();
|
||||||
WiFiClientSecure(const WiFiClientSecure &rhs);
|
WiFiClientSecureCtx(const WiFiClientSecure &rhs) = delete;
|
||||||
~WiFiClientSecure() override;
|
~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(IPAddress ip, uint16_t port) override;
|
||||||
int connect(const String& host, 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;
|
uint8_t connected() override;
|
||||||
size_t write(const uint8_t *buf, size_t size) 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_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
|
size_t write(Stream& stream); // Note this is not virtual
|
||||||
int read(uint8_t *buf, size_t size) override;
|
int read(uint8_t *buf, size_t size) override;
|
||||||
int available() override;
|
int available() override;
|
||||||
@ -123,14 +117,9 @@ class WiFiClientSecure : public WiFiClient {
|
|||||||
// Select specific ciphers (i.e. optimize for speed over security)
|
// Select specific ciphers (i.e. optimize for speed over security)
|
||||||
// These may be in PROGMEM or RAM, either will run properly
|
// These may be in PROGMEM or RAM, either will run properly
|
||||||
bool setCiphers(const uint16_t *cipherAry, int cipherCount);
|
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
|
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:
|
protected:
|
||||||
bool _connectSSL(const char *hostName); // Do initial SSL handshake
|
bool _connectSSL(const char *hostName); // Do initial SSL handshake
|
||||||
|
|
||||||
@ -188,10 +177,10 @@ class WiFiClientSecure : public WiFiClient {
|
|||||||
unsigned _cert_issuer_key_type;
|
unsigned _cert_issuer_key_type;
|
||||||
|
|
||||||
// Methods for handling server.available() call which returns a client connection.
|
// Methods for handling server.available() call which returns a client connection.
|
||||||
friend class WiFiServerSecure; // Server needs to access these constructors
|
friend class WiFiClientSecure; // access to private context constructors
|
||||||
WiFiClientSecure(ClientContext *client, const X509List *chain, unsigned cert_issuer_key_type,
|
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);
|
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,
|
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, const X509List *client_CA_ta);
|
||||||
|
|
||||||
// RSA keyed server
|
// RSA keyed server
|
||||||
@ -205,8 +194,113 @@ class WiFiClientSecure : public WiFiClient {
|
|||||||
bool _installServerX509Validator(const X509List *client_CA_ta); // Setup X509 client cert validation, if supplied
|
bool _installServerX509Validator(const X509List *client_CA_ta); // Setup X509 client cert validation, if supplied
|
||||||
|
|
||||||
uint8_t *_streamLoad(Stream& stream, size_t size);
|
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(CertStore *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, const X509List *client_CA_ta):
|
||||||
|
_ctx(new WiFiClientSecureCtx(client, chain, cert_issuer_key_type, sk, iobuf_in_size, iobuf_out_size, 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):
|
||||||
|
_ctx(new WiFiClientSecureCtx(client, chain, sk, iobuf_in_size, iobuf_out_size, client_CA_ta)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class WiFiClientSecure
|
||||||
|
|
||||||
|
}; // namespace BearSSL
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user