mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-25 20:02:37 +03:00
Add setSSLVersion call to SSL object (#7920)
* Add setSSLVersion call to SSL object Allow users to only allow specific TLS versions for connections with an additional call in their app, similar to the setCiphers call. Fixes #7918 * Add SSL level options to WiFiServerSecure
This commit is contained in:
parent
dcdd4313cb
commit
7475ba7ff3
@ -20,7 +20,7 @@ BearSSL doesn't perform memory allocations at runtime, but it does require alloc
|
|||||||
. A per-application secondary stack
|
. A per-application secondary stack
|
||||||
. A per-connection TLS receive/transmit buffer plus overhead
|
. A per-connection TLS receive/transmit buffer plus overhead
|
||||||
|
|
||||||
The per-application secondary stack is approximately 5.6KB in size and is used for temporary variables during BearSSL processing. Only one stack is required, and it will be allocated whenever any `BearSSL::WiFiClientSecure` or `BearSSL::WiFiServerSecure` are instantiated. So, in the case of a global client or server, the memory will be allocated before `setup()` is called.
|
The per-application secondary stack is approximately 6KB in size and is used for temporary variables during BearSSL processing. Only one stack is required, and it will be allocated whenever any `BearSSL::WiFiClientSecure` or `BearSSL::WiFiServerSecure` are instantiated. So, in the case of a global client or server, the memory will be allocated before `setup()` is called.
|
||||||
|
|
||||||
The per-connection buffers are approximately 22KB in size, but in certain circumstances it can be reduced dramatically by using MFLN or limiting message sizes. See the `MLFN section <#mfln-or-maximum-fragment-length-negotiation-saving-ram>`__ below for more information.
|
The per-connection buffers are approximately 22KB in size, but in certain circumstances it can be reduced dramatically by using MFLN or limiting message sizes. See the `MLFN section <#mfln-or-maximum-fragment-length-negotiation-saving-ram>`__ below for more information.
|
||||||
|
|
||||||
@ -219,3 +219,13 @@ setCiphersLessSecure()
|
|||||||
^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Helper function which essentially limits BearSSL to less secure ciphers than it would natively choose, but they may be helpful and faster if your server depended on specific crypto options.
|
Helper function which essentially limits BearSSL to less secure ciphers than it would natively choose, but they may be helpful and faster if your server depended on specific crypto options.
|
||||||
|
|
||||||
|
Limiting TLS(SSL) Versions
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
By default, BearSSL will connect with TLS 1.0, TLS 1.1, or TLS 1.2 protocols (depending on the request of the remote side). If you want to limit to a subset, use the following call:
|
||||||
|
|
||||||
|
setSSLVersion(uint32_t min, uint32_t max)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Valid values for min and max are `BR_TLS10`, `BR_TLS11`, `BR_TLS12`. Min and max may be set to the same value if only a single TLS version is desired.
|
||||||
|
@ -156,6 +156,7 @@ loadCertificate KEYWORD2
|
|||||||
loadPrivateKey KEYWORD2
|
loadPrivateKey KEYWORD2
|
||||||
loadCACert KEYWORD2
|
loadCACert KEYWORD2
|
||||||
allowSelfSignedCerts KEYWORD2
|
allowSelfSignedCerts KEYWORD2
|
||||||
|
setSSLVersion KEYWORD2
|
||||||
|
|
||||||
#WiFiServer
|
#WiFiServer
|
||||||
hasClient KEYWORD2
|
hasClient KEYWORD2
|
||||||
|
@ -93,6 +93,8 @@ void WiFiClientSecureCtx::_clear() {
|
|||||||
_session = nullptr;
|
_session = nullptr;
|
||||||
_cipher_list = nullptr;
|
_cipher_list = nullptr;
|
||||||
_cipher_cnt = 0;
|
_cipher_cnt = 0;
|
||||||
|
_tls_min = BR_TLS10;
|
||||||
|
_tls_max = BR_TLS12;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WiFiClientSecureCtx::_clearAuthenticationSettings() {
|
void WiFiClientSecureCtx::_clearAuthenticationSettings() {
|
||||||
@ -125,7 +127,7 @@ WiFiClientSecureCtx::~WiFiClientSecureCtx() {
|
|||||||
WiFiClientSecureCtx::WiFiClientSecureCtx(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, ServerSessions *cache,
|
int iobuf_in_size, int iobuf_out_size, ServerSessions *cache,
|
||||||
const X509List *client_CA_ta) {
|
const X509List *client_CA_ta, int tls_min, int tls_max) {
|
||||||
_clear();
|
_clear();
|
||||||
_clearAuthenticationSettings();
|
_clearAuthenticationSettings();
|
||||||
stack_thunk_add_ref();
|
stack_thunk_add_ref();
|
||||||
@ -133,6 +135,8 @@ WiFiClientSecureCtx::WiFiClientSecureCtx(ClientContext* client,
|
|||||||
_iobuf_out_size = iobuf_out_size;
|
_iobuf_out_size = iobuf_out_size;
|
||||||
_client = client;
|
_client = client;
|
||||||
_client->ref();
|
_client->ref();
|
||||||
|
_tls_min = tls_min;
|
||||||
|
_tls_max = tls_max;
|
||||||
if (!_connectSSLServerRSA(chain, sk, cache, client_CA_ta)) {
|
if (!_connectSSLServerRSA(chain, sk, cache, client_CA_ta)) {
|
||||||
_client->unref();
|
_client->unref();
|
||||||
_client = nullptr;
|
_client = nullptr;
|
||||||
@ -144,7 +148,7 @@ 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, ServerSessions *cache,
|
int iobuf_in_size, int iobuf_out_size, ServerSessions *cache,
|
||||||
const X509List *client_CA_ta) {
|
const X509List *client_CA_ta, int tls_min, int tls_max) {
|
||||||
_clear();
|
_clear();
|
||||||
_clearAuthenticationSettings();
|
_clearAuthenticationSettings();
|
||||||
stack_thunk_add_ref();
|
stack_thunk_add_ref();
|
||||||
@ -152,6 +156,8 @@ WiFiClientSecureCtx::WiFiClientSecureCtx(ClientContext *client,
|
|||||||
_iobuf_out_size = iobuf_out_size;
|
_iobuf_out_size = iobuf_out_size;
|
||||||
_client = client;
|
_client = client;
|
||||||
_client->ref();
|
_client->ref();
|
||||||
|
_tls_min = tls_min;
|
||||||
|
_tls_max = tls_max;
|
||||||
if (!_connectSSLServerEC(chain, cert_issuer_key_type, sk, cache, client_CA_ta)) {
|
if (!_connectSSLServerEC(chain, cert_issuer_key_type, sk, cache, client_CA_ta)) {
|
||||||
_client->unref();
|
_client->unref();
|
||||||
_client = nullptr;
|
_client = nullptr;
|
||||||
@ -1005,6 +1011,17 @@ bool WiFiClientSecureCtx::setCiphers(const std::vector<uint16_t>& list) {
|
|||||||
return setCiphers(&list[0], list.size());
|
return setCiphers(&list[0], list.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WiFiClientSecureCtx::setSSLVersion(uint32_t min, uint32_t max) {
|
||||||
|
if ( ((min != BR_TLS10) && (min != BR_TLS11) && (min != BR_TLS12)) ||
|
||||||
|
((max != BR_TLS10) && (max != BR_TLS11) && (max != BR_TLS12)) ||
|
||||||
|
(max < min) ) {
|
||||||
|
return false; // Invalid options
|
||||||
|
}
|
||||||
|
_tls_min = min;
|
||||||
|
_tls_max = max;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Installs the appropriate X509 cert validation method for a client connection
|
// Installs the appropriate X509 cert validation method for a client connection
|
||||||
bool WiFiClientSecureCtx::_installClientX509Validator() {
|
bool WiFiClientSecureCtx::_installClientX509Validator() {
|
||||||
if (_use_insecure || _use_fingerprint || _use_self_signed) {
|
if (_use_insecure || _use_fingerprint || _use_self_signed) {
|
||||||
@ -1110,6 +1127,7 @@ bool WiFiClientSecureCtx::_connectSSL(const char* hostName) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
br_ssl_engine_set_buffers_bidi(_eng, _iobuf_in.get(), _iobuf_in_size, _iobuf_out.get(), _iobuf_out_size);
|
br_ssl_engine_set_buffers_bidi(_eng, _iobuf_in.get(), _iobuf_in_size, _iobuf_out.get(), _iobuf_out_size);
|
||||||
|
br_ssl_engine_set_versions(_eng, _tls_min, _tls_max);
|
||||||
|
|
||||||
// Apply any client certificates, if supplied.
|
// Apply any client certificates, if supplied.
|
||||||
if (_sk && _sk->isRSA()) {
|
if (_sk && _sk->isRSA()) {
|
||||||
@ -1224,6 +1242,7 @@ bool WiFiClientSecureCtx::_connectSSLServerRSA(const X509List *chain,
|
|||||||
sk ? sk->getRSA() : nullptr, BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN,
|
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);
|
br_ssl_engine_set_buffers_bidi(_eng, _iobuf_in.get(), _iobuf_in_size, _iobuf_out.get(), _iobuf_out_size);
|
||||||
|
br_ssl_engine_set_versions(_eng, _tls_min, _tls_max);
|
||||||
if (cache != nullptr)
|
if (cache != nullptr)
|
||||||
br_ssl_server_set_cache(_sc_svr.get(), cache->getCache());
|
br_ssl_server_set_cache(_sc_svr.get(), cache->getCache());
|
||||||
if (client_CA_ta && !_installServerX509Validator(client_CA_ta)) {
|
if (client_CA_ta && !_installServerX509Validator(client_CA_ta)) {
|
||||||
@ -1270,6 +1289,7 @@ bool WiFiClientSecureCtx::_connectSSLServerEC(const X509List *chain,
|
|||||||
sk ? sk->getEC() : nullptr, BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN,
|
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);
|
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);
|
br_ssl_engine_set_buffers_bidi(_eng, _iobuf_in.get(), _iobuf_in_size, _iobuf_out.get(), _iobuf_out_size);
|
||||||
|
br_ssl_engine_set_versions(_eng, _tls_min, _tls_max);
|
||||||
if (cache != nullptr)
|
if (cache != nullptr)
|
||||||
br_ssl_server_set_cache(_sc_svr.get(), cache->getCache());
|
br_ssl_server_set_cache(_sc_svr.get(), cache->getCache());
|
||||||
if (client_CA_ta && !_installServerX509Validator(client_CA_ta)) {
|
if (client_CA_ta && !_installServerX509Validator(client_CA_ta)) {
|
||||||
|
@ -121,6 +121,10 @@ class WiFiClientSecureCtx : public WiFiClient {
|
|||||||
bool setCiphers(const 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
|
||||||
|
|
||||||
|
// Limit the TLS versions BearSSL will connect with. Default is
|
||||||
|
// BR_TLS10...BR_TLS12
|
||||||
|
bool setSSLVersion(uint32_t min = BR_TLS10, uint32_t max = BR_TLS12);
|
||||||
|
|
||||||
// peek buffer API is present
|
// peek buffer API is present
|
||||||
virtual bool hasPeekBufferAPI () const override { return true; }
|
virtual bool hasPeekBufferAPI () const override { return true; }
|
||||||
|
|
||||||
@ -175,6 +179,10 @@ class WiFiClientSecureCtx : public WiFiClient {
|
|||||||
std::shared_ptr<uint16_t> _cipher_list;
|
std::shared_ptr<uint16_t> _cipher_list;
|
||||||
uint8_t _cipher_cnt;
|
uint8_t _cipher_cnt;
|
||||||
|
|
||||||
|
// TLS ciphers allowed
|
||||||
|
uint32_t _tls_min;
|
||||||
|
uint32_t _tls_max;
|
||||||
|
|
||||||
unsigned char *_recvapp_buf;
|
unsigned char *_recvapp_buf;
|
||||||
size_t _recvapp_len;
|
size_t _recvapp_len;
|
||||||
|
|
||||||
@ -194,10 +202,10 @@ class WiFiClientSecureCtx : public WiFiClient {
|
|||||||
friend class WiFiClientSecure; // access to private context constructors
|
friend class WiFiClientSecure; // access to private context constructors
|
||||||
WiFiClientSecureCtx(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, ServerSessions *cache,
|
const PrivateKey *sk, int iobuf_in_size, int iobuf_out_size, ServerSessions *cache,
|
||||||
const X509List *client_CA_ta);
|
const X509List *client_CA_ta, int tls_min, int tls_max);
|
||||||
WiFiClientSecureCtx(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, ServerSessions *cache,
|
int iobuf_in_size, int iobuf_out_size, ServerSessions *cache,
|
||||||
const X509List *client_CA_ta);
|
const X509List *client_CA_ta, int tls_min, int tls_max);
|
||||||
|
|
||||||
// RSA keyed server
|
// RSA keyed server
|
||||||
bool _connectSSLServerRSA(const X509List *chain, const PrivateKey *sk,
|
bool _connectSSLServerRSA(const X509List *chain, const PrivateKey *sk,
|
||||||
@ -321,14 +329,14 @@ class WiFiClientSecure : public WiFiClient {
|
|||||||
friend class WiFiServerSecure; // Server needs to access these constructors
|
friend class WiFiServerSecure; // Server needs to access these constructors
|
||||||
WiFiClientSecure(ClientContext *client, const X509List *chain, unsigned cert_issuer_key_type,
|
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 PrivateKey *sk, int iobuf_in_size, int iobuf_out_size, ServerSessions *cache,
|
||||||
const X509List *client_CA_ta):
|
const X509List *client_CA_ta, int tls_min, int tls_max):
|
||||||
_ctx(new WiFiClientSecureCtx(client, chain, cert_issuer_key_type, sk, iobuf_in_size, iobuf_out_size, cache, client_CA_ta)) {
|
_ctx(new WiFiClientSecureCtx(client, chain, cert_issuer_key_type, sk, iobuf_in_size, iobuf_out_size, cache, client_CA_ta, tls_min, tls_max)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
WiFiClientSecure(ClientContext* client, const X509List *chain, const PrivateKey *sk,
|
WiFiClientSecure(ClientContext* client, const X509List *chain, const PrivateKey *sk,
|
||||||
int iobuf_in_size, int iobuf_out_size, ServerSessions *cache,
|
int iobuf_in_size, int iobuf_out_size, ServerSessions *cache,
|
||||||
const X509List *client_CA_ta):
|
const X509List *client_CA_ta, int tls_min, int tls_max):
|
||||||
_ctx(new WiFiClientSecureCtx(client, chain, sk, iobuf_in_size, iobuf_out_size, cache, client_CA_ta)) {
|
_ctx(new WiFiClientSecureCtx(client, chain, sk, iobuf_in_size, iobuf_out_size, cache, client_CA_ta, tls_min, tls_max)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // class WiFiClientSecure
|
}; // class WiFiClientSecure
|
||||||
|
@ -79,13 +79,13 @@ WiFiClientSecure WiFiServerSecure::available(uint8_t* status) {
|
|||||||
(void) status; // Unused
|
(void) status; // Unused
|
||||||
if (_unclaimed) {
|
if (_unclaimed) {
|
||||||
if (_sk && _sk->isRSA()) {
|
if (_sk && _sk->isRSA()) {
|
||||||
WiFiClientSecure result(_unclaimed, _chain, _sk, _iobuf_in_size, _iobuf_out_size, _cache, _client_CA_ta);
|
WiFiClientSecure result(_unclaimed, _chain, _sk, _iobuf_in_size, _iobuf_out_size, _cache, _client_CA_ta, _tls_min, _tls_max);
|
||||||
_unclaimed = _unclaimed->next();
|
_unclaimed = _unclaimed->next();
|
||||||
result.setNoDelay(_noDelay);
|
result.setNoDelay(_noDelay);
|
||||||
DEBUGV("WS:av\r\n");
|
DEBUGV("WS:av\r\n");
|
||||||
return result;
|
return result;
|
||||||
} else if (_sk && _sk->isEC()) {
|
} else if (_sk && _sk->isEC()) {
|
||||||
WiFiClientSecure result(_unclaimed, _chain, _cert_issuer_key_type, _sk, _iobuf_in_size, _iobuf_out_size, _cache, _client_CA_ta);
|
WiFiClientSecure result(_unclaimed, _chain, _cert_issuer_key_type, _sk, _iobuf_in_size, _iobuf_out_size, _cache, _client_CA_ta, _tls_min, _tls_max);
|
||||||
_unclaimed = _unclaimed->next();
|
_unclaimed = _unclaimed->next();
|
||||||
result.setNoDelay(_noDelay);
|
result.setNoDelay(_noDelay);
|
||||||
DEBUGV("WS:av\r\n");
|
DEBUGV("WS:av\r\n");
|
||||||
@ -101,4 +101,15 @@ WiFiClientSecure WiFiServerSecure::available(uint8_t* status) {
|
|||||||
return WiFiClientSecure();
|
return WiFiClientSecure();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WiFiServerSecure::setSSLVersion(uint32_t min, uint32_t max) {
|
||||||
|
if ( ((min != BR_TLS10) && (min != BR_TLS11) && (min != BR_TLS12)) ||
|
||||||
|
((max != BR_TLS10) && (max != BR_TLS11) && (max != BR_TLS12)) ||
|
||||||
|
(max < min) ) {
|
||||||
|
return false; // Invalid options
|
||||||
|
}
|
||||||
|
_tls_min = min;
|
||||||
|
_tls_max = max;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -60,6 +60,10 @@ class WiFiServerSecure : public WiFiServer {
|
|||||||
_client_CA_ta = client_CA_ta;
|
_client_CA_ta = client_CA_ta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Limit the TLS versions BearSSL will connect with. Default is
|
||||||
|
// BR_TLS10...BR_TLS12
|
||||||
|
bool setSSLVersion(uint32_t min = BR_TLS10, uint32_t max = BR_TLS12);
|
||||||
|
|
||||||
// If awaiting connection available and authenticated (i.e. client cert), return it.
|
// If awaiting connection available and authenticated (i.e. client cert), return it.
|
||||||
WiFiClientSecure available(uint8_t* status = NULL);
|
WiFiClientSecure available(uint8_t* status = NULL);
|
||||||
|
|
||||||
@ -76,6 +80,9 @@ class WiFiServerSecure : public WiFiServer {
|
|||||||
const X509List *_client_CA_ta = nullptr;
|
const X509List *_client_CA_ta = nullptr;
|
||||||
ServerSessions *_cache = nullptr;
|
ServerSessions *_cache = nullptr;
|
||||||
|
|
||||||
|
// TLS ciphers allowed
|
||||||
|
uint32_t _tls_min = BR_TLS10;
|
||||||
|
uint32_t _tls_max = BR_TLS12;
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user