mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-19 23:22:16 +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-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.
|
||||
|
||||
@ -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.
|
||||
|
||||
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
|
||||
loadCACert KEYWORD2
|
||||
allowSelfSignedCerts KEYWORD2
|
||||
setSSLVersion KEYWORD2
|
||||
|
||||
#WiFiServer
|
||||
hasClient KEYWORD2
|
||||
|
@ -93,6 +93,8 @@ void WiFiClientSecureCtx::_clear() {
|
||||
_session = nullptr;
|
||||
_cipher_list = nullptr;
|
||||
_cipher_cnt = 0;
|
||||
_tls_min = BR_TLS10;
|
||||
_tls_max = BR_TLS12;
|
||||
}
|
||||
|
||||
void WiFiClientSecureCtx::_clearAuthenticationSettings() {
|
||||
@ -125,7 +127,7 @@ WiFiClientSecureCtx::~WiFiClientSecureCtx() {
|
||||
WiFiClientSecureCtx::WiFiClientSecureCtx(ClientContext* client,
|
||||
const X509List *chain, 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) {
|
||||
_clear();
|
||||
_clearAuthenticationSettings();
|
||||
stack_thunk_add_ref();
|
||||
@ -133,6 +135,8 @@ WiFiClientSecureCtx::WiFiClientSecureCtx(ClientContext* client,
|
||||
_iobuf_out_size = iobuf_out_size;
|
||||
_client = client;
|
||||
_client->ref();
|
||||
_tls_min = tls_min;
|
||||
_tls_max = tls_max;
|
||||
if (!_connectSSLServerRSA(chain, sk, cache, client_CA_ta)) {
|
||||
_client->unref();
|
||||
_client = nullptr;
|
||||
@ -144,7 +148,7 @@ WiFiClientSecureCtx::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) {
|
||||
const X509List *client_CA_ta, int tls_min, int tls_max) {
|
||||
_clear();
|
||||
_clearAuthenticationSettings();
|
||||
stack_thunk_add_ref();
|
||||
@ -152,6 +156,8 @@ WiFiClientSecureCtx::WiFiClientSecureCtx(ClientContext *client,
|
||||
_iobuf_out_size = iobuf_out_size;
|
||||
_client = client;
|
||||
_client->ref();
|
||||
_tls_min = tls_min;
|
||||
_tls_max = tls_max;
|
||||
if (!_connectSSLServerEC(chain, cert_issuer_key_type, sk, cache, client_CA_ta)) {
|
||||
_client->unref();
|
||||
_client = nullptr;
|
||||
@ -1005,6 +1011,17 @@ bool WiFiClientSecureCtx::setCiphers(const std::vector<uint16_t>& list) {
|
||||
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
|
||||
bool WiFiClientSecureCtx::_installClientX509Validator() {
|
||||
if (_use_insecure || _use_fingerprint || _use_self_signed) {
|
||||
@ -1110,6 +1127,7 @@ bool WiFiClientSecureCtx::_connectSSL(const char* hostName) {
|
||||
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_versions(_eng, _tls_min, _tls_max);
|
||||
|
||||
// Apply any client certificates, if supplied.
|
||||
if (_sk && _sk->isRSA()) {
|
||||
@ -1224,6 +1242,7 @@ bool WiFiClientSecureCtx::_connectSSLServerRSA(const X509List *chain,
|
||||
sk ? sk->getRSA() : nullptr, BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN,
|
||||
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_versions(_eng, _tls_min, _tls_max);
|
||||
if (cache != nullptr)
|
||||
br_ssl_server_set_cache(_sc_svr.get(), cache->getCache());
|
||||
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,
|
||||
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_versions(_eng, _tls_min, _tls_max);
|
||||
if (cache != nullptr)
|
||||
br_ssl_server_set_cache(_sc_svr.get(), cache->getCache());
|
||||
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 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
|
||||
virtual bool hasPeekBufferAPI () const override { return true; }
|
||||
|
||||
@ -175,6 +179,10 @@ class WiFiClientSecureCtx : public WiFiClient {
|
||||
std::shared_ptr<uint16_t> _cipher_list;
|
||||
uint8_t _cipher_cnt;
|
||||
|
||||
// TLS ciphers allowed
|
||||
uint32_t _tls_min;
|
||||
uint32_t _tls_max;
|
||||
|
||||
unsigned char *_recvapp_buf;
|
||||
size_t _recvapp_len;
|
||||
|
||||
@ -194,10 +202,10 @@ class WiFiClientSecureCtx : public WiFiClient {
|
||||
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);
|
||||
const X509List *client_CA_ta, int tls_min, int tls_max);
|
||||
WiFiClientSecureCtx(ClientContext* client, const X509List *chain, 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);
|
||||
|
||||
// RSA keyed server
|
||||
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
|
||||
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)) {
|
||||
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, tls_min, tls_max)) {
|
||||
}
|
||||
|
||||
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)) {
|
||||
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, tls_min, tls_max)) {
|
||||
}
|
||||
|
||||
}; // class WiFiClientSecure
|
||||
|
@ -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, _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();
|
||||
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, _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();
|
||||
result.setNoDelay(_noDelay);
|
||||
DEBUGV("WS:av\r\n");
|
||||
@ -101,4 +101,15 @@ WiFiClientSecure WiFiServerSecure::available(uint8_t* status) {
|
||||
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;
|
||||
}
|
||||
|
||||
// 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.
|
||||
WiFiClientSecure available(uint8_t* status = NULL);
|
||||
|
||||
@ -76,6 +80,9 @@ class WiFiServerSecure : public WiFiServer {
|
||||
const X509List *_client_CA_ta = 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