Skip to content

Commit 7475ba7

Browse files
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
1 parent dcdd431 commit 7475ba7

6 files changed

+68
-11
lines changed

Diff for: doc/esp8266wifi/bearssl-client-secure-class.rst

+11-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ BearSSL doesn't perform memory allocations at runtime, but it does require alloc
2020
. A per-application secondary stack
2121
. A per-connection TLS receive/transmit buffer plus overhead
2222

23-
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.
23+
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.
2424

2525
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.
2626

@@ -219,3 +219,13 @@ setCiphersLessSecure()
219219
^^^^^^^^^^^^^^^^^^^^^^
220220

221221
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.
222+
223+
Limiting TLS(SSL) Versions
224+
~~~~~~~~~~~~~~~~~~~~~~~~~~
225+
226+
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:
227+
228+
setSSLVersion(uint32_t min, uint32_t max)
229+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
230+
231+
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.

Diff for: libraries/ESP8266WiFi/keywords.txt

+1
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ loadCertificate KEYWORD2
156156
loadPrivateKey KEYWORD2
157157
loadCACert KEYWORD2
158158
allowSelfSignedCerts KEYWORD2
159+
setSSLVersion KEYWORD2
159160

160161
#WiFiServer
161162
hasClient KEYWORD2

Diff for: libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp

+22-2
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ void WiFiClientSecureCtx::_clear() {
9393
_session = nullptr;
9494
_cipher_list = nullptr;
9595
_cipher_cnt = 0;
96+
_tls_min = BR_TLS10;
97+
_tls_max = BR_TLS12;
9698
}
9799

98100
void WiFiClientSecureCtx::_clearAuthenticationSettings() {
@@ -125,14 +127,16 @@ WiFiClientSecureCtx::~WiFiClientSecureCtx() {
125127
WiFiClientSecureCtx::WiFiClientSecureCtx(ClientContext* client,
126128
const X509List *chain, const PrivateKey *sk,
127129
int iobuf_in_size, int iobuf_out_size, ServerSessions *cache,
128-
const X509List *client_CA_ta) {
130+
const X509List *client_CA_ta, int tls_min, int tls_max) {
129131
_clear();
130132
_clearAuthenticationSettings();
131133
stack_thunk_add_ref();
132134
_iobuf_in_size = iobuf_in_size;
133135
_iobuf_out_size = iobuf_out_size;
134136
_client = client;
135137
_client->ref();
138+
_tls_min = tls_min;
139+
_tls_max = tls_max;
136140
if (!_connectSSLServerRSA(chain, sk, cache, client_CA_ta)) {
137141
_client->unref();
138142
_client = nullptr;
@@ -144,14 +148,16 @@ WiFiClientSecureCtx::WiFiClientSecureCtx(ClientContext *client,
144148
const X509List *chain,
145149
unsigned cert_issuer_key_type, const PrivateKey *sk,
146150
int iobuf_in_size, int iobuf_out_size, ServerSessions *cache,
147-
const X509List *client_CA_ta) {
151+
const X509List *client_CA_ta, int tls_min, int tls_max) {
148152
_clear();
149153
_clearAuthenticationSettings();
150154
stack_thunk_add_ref();
151155
_iobuf_in_size = iobuf_in_size;
152156
_iobuf_out_size = iobuf_out_size;
153157
_client = client;
154158
_client->ref();
159+
_tls_min = tls_min;
160+
_tls_max = tls_max;
155161
if (!_connectSSLServerEC(chain, cert_issuer_key_type, sk, cache, client_CA_ta)) {
156162
_client->unref();
157163
_client = nullptr;
@@ -1005,6 +1011,17 @@ bool WiFiClientSecureCtx::setCiphers(const std::vector<uint16_t>& list) {
10051011
return setCiphers(&list[0], list.size());
10061012
}
10071013

1014+
bool WiFiClientSecureCtx::setSSLVersion(uint32_t min, uint32_t max) {
1015+
if ( ((min != BR_TLS10) && (min != BR_TLS11) && (min != BR_TLS12)) ||
1016+
((max != BR_TLS10) && (max != BR_TLS11) && (max != BR_TLS12)) ||
1017+
(max < min) ) {
1018+
return false; // Invalid options
1019+
}
1020+
_tls_min = min;
1021+
_tls_max = max;
1022+
return true;
1023+
}
1024+
10081025
// Installs the appropriate X509 cert validation method for a client connection
10091026
bool WiFiClientSecureCtx::_installClientX509Validator() {
10101027
if (_use_insecure || _use_fingerprint || _use_self_signed) {
@@ -1110,6 +1127,7 @@ bool WiFiClientSecureCtx::_connectSSL(const char* hostName) {
11101127
return false;
11111128
}
11121129
br_ssl_engine_set_buffers_bidi(_eng, _iobuf_in.get(), _iobuf_in_size, _iobuf_out.get(), _iobuf_out_size);
1130+
br_ssl_engine_set_versions(_eng, _tls_min, _tls_max);
11131131

11141132
// Apply any client certificates, if supplied.
11151133
if (_sk && _sk->isRSA()) {
@@ -1224,6 +1242,7 @@ bool WiFiClientSecureCtx::_connectSSLServerRSA(const X509List *chain,
12241242
sk ? sk->getRSA() : nullptr, BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN,
12251243
br_rsa_private_get_default(), br_rsa_pkcs1_sign_get_default());
12261244
br_ssl_engine_set_buffers_bidi(_eng, _iobuf_in.get(), _iobuf_in_size, _iobuf_out.get(), _iobuf_out_size);
1245+
br_ssl_engine_set_versions(_eng, _tls_min, _tls_max);
12271246
if (cache != nullptr)
12281247
br_ssl_server_set_cache(_sc_svr.get(), cache->getCache());
12291248
if (client_CA_ta && !_installServerX509Validator(client_CA_ta)) {
@@ -1270,6 +1289,7 @@ bool WiFiClientSecureCtx::_connectSSLServerEC(const X509List *chain,
12701289
sk ? sk->getEC() : nullptr, BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN,
12711290
cert_issuer_key_type, br_ssl_engine_get_ec(_eng), br_ecdsa_i15_sign_asn1);
12721291
br_ssl_engine_set_buffers_bidi(_eng, _iobuf_in.get(), _iobuf_in_size, _iobuf_out.get(), _iobuf_out_size);
1292+
br_ssl_engine_set_versions(_eng, _tls_min, _tls_max);
12731293
if (cache != nullptr)
12741294
br_ssl_server_set_cache(_sc_svr.get(), cache->getCache());
12751295
if (client_CA_ta && !_installServerX509Validator(client_CA_ta)) {

Diff for: libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.h

+14-6
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ class WiFiClientSecureCtx : public WiFiClient {
121121
bool setCiphers(const std::vector<uint16_t>& list);
122122
bool setCiphersLessSecure(); // Only use the limited set of RSA ciphers without EC
123123

124+
// Limit the TLS versions BearSSL will connect with. Default is
125+
// BR_TLS10...BR_TLS12
126+
bool setSSLVersion(uint32_t min = BR_TLS10, uint32_t max = BR_TLS12);
127+
124128
// peek buffer API is present
125129
virtual bool hasPeekBufferAPI () const override { return true; }
126130

@@ -175,6 +179,10 @@ class WiFiClientSecureCtx : public WiFiClient {
175179
std::shared_ptr<uint16_t> _cipher_list;
176180
uint8_t _cipher_cnt;
177181

182+
// TLS ciphers allowed
183+
uint32_t _tls_min;
184+
uint32_t _tls_max;
185+
178186
unsigned char *_recvapp_buf;
179187
size_t _recvapp_len;
180188

@@ -194,10 +202,10 @@ class WiFiClientSecureCtx : public WiFiClient {
194202
friend class WiFiClientSecure; // access to private context constructors
195203
WiFiClientSecureCtx(ClientContext *client, const X509List *chain, unsigned cert_issuer_key_type,
196204
const PrivateKey *sk, int iobuf_in_size, int iobuf_out_size, ServerSessions *cache,
197-
const X509List *client_CA_ta);
205+
const X509List *client_CA_ta, int tls_min, int tls_max);
198206
WiFiClientSecureCtx(ClientContext* client, const X509List *chain, const PrivateKey *sk,
199207
int iobuf_in_size, int iobuf_out_size, ServerSessions *cache,
200-
const X509List *client_CA_ta);
208+
const X509List *client_CA_ta, int tls_min, int tls_max);
201209

202210
// RSA keyed server
203211
bool _connectSSLServerRSA(const X509List *chain, const PrivateKey *sk,
@@ -321,14 +329,14 @@ class WiFiClientSecure : public WiFiClient {
321329
friend class WiFiServerSecure; // Server needs to access these constructors
322330
WiFiClientSecure(ClientContext *client, const X509List *chain, unsigned cert_issuer_key_type,
323331
const PrivateKey *sk, int iobuf_in_size, int iobuf_out_size, ServerSessions *cache,
324-
const X509List *client_CA_ta):
325-
_ctx(new WiFiClientSecureCtx(client, chain, cert_issuer_key_type, sk, iobuf_in_size, iobuf_out_size, cache, client_CA_ta)) {
332+
const X509List *client_CA_ta, int tls_min, int tls_max):
333+
_ctx(new WiFiClientSecureCtx(client, chain, cert_issuer_key_type, sk, iobuf_in_size, iobuf_out_size, cache, client_CA_ta, tls_min, tls_max)) {
326334
}
327335

328336
WiFiClientSecure(ClientContext* client, const X509List *chain, const PrivateKey *sk,
329337
int iobuf_in_size, int iobuf_out_size, ServerSessions *cache,
330-
const X509List *client_CA_ta):
331-
_ctx(new WiFiClientSecureCtx(client, chain, sk, iobuf_in_size, iobuf_out_size, cache, client_CA_ta)) {
338+
const X509List *client_CA_ta, int tls_min, int tls_max):
339+
_ctx(new WiFiClientSecureCtx(client, chain, sk, iobuf_in_size, iobuf_out_size, cache, client_CA_ta, tls_min, tls_max)) {
332340
}
333341

334342
}; // class WiFiClientSecure

Diff for: libraries/ESP8266WiFi/src/WiFiServerSecureBearSSL.cpp

+13-2
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,13 @@ WiFiClientSecure WiFiServerSecure::available(uint8_t* status) {
7979
(void) status; // Unused
8080
if (_unclaimed) {
8181
if (_sk && _sk->isRSA()) {
82-
WiFiClientSecure result(_unclaimed, _chain, _sk, _iobuf_in_size, _iobuf_out_size, _cache, _client_CA_ta);
82+
WiFiClientSecure result(_unclaimed, _chain, _sk, _iobuf_in_size, _iobuf_out_size, _cache, _client_CA_ta, _tls_min, _tls_max);
8383
_unclaimed = _unclaimed->next();
8484
result.setNoDelay(_noDelay);
8585
DEBUGV("WS:av\r\n");
8686
return result;
8787
} else if (_sk && _sk->isEC()) {
88-
WiFiClientSecure result(_unclaimed, _chain, _cert_issuer_key_type, _sk, _iobuf_in_size, _iobuf_out_size, _cache, _client_CA_ta);
88+
WiFiClientSecure result(_unclaimed, _chain, _cert_issuer_key_type, _sk, _iobuf_in_size, _iobuf_out_size, _cache, _client_CA_ta, _tls_min, _tls_max);
8989
_unclaimed = _unclaimed->next();
9090
result.setNoDelay(_noDelay);
9191
DEBUGV("WS:av\r\n");
@@ -101,4 +101,15 @@ WiFiClientSecure WiFiServerSecure::available(uint8_t* status) {
101101
return WiFiClientSecure();
102102
}
103103

104+
bool WiFiServerSecure::setSSLVersion(uint32_t min, uint32_t max) {
105+
if ( ((min != BR_TLS10) && (min != BR_TLS11) && (min != BR_TLS12)) ||
106+
((max != BR_TLS10) && (max != BR_TLS11) && (max != BR_TLS12)) ||
107+
(max < min) ) {
108+
return false; // Invalid options
109+
}
110+
_tls_min = min;
111+
_tls_max = max;
112+
return true;
113+
}
114+
104115
};

Diff for: libraries/ESP8266WiFi/src/WiFiServerSecureBearSSL.h

+7
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ class WiFiServerSecure : public WiFiServer {
6060
_client_CA_ta = client_CA_ta;
6161
}
6262

63+
// Limit the TLS versions BearSSL will connect with. Default is
64+
// BR_TLS10...BR_TLS12
65+
bool setSSLVersion(uint32_t min = BR_TLS10, uint32_t max = BR_TLS12);
66+
6367
// If awaiting connection available and authenticated (i.e. client cert), return it.
6468
WiFiClientSecure available(uint8_t* status = NULL);
6569

@@ -76,6 +80,9 @@ class WiFiServerSecure : public WiFiServer {
7680
const X509List *_client_CA_ta = nullptr;
7781
ServerSessions *_cache = nullptr;
7882

83+
// TLS ciphers allowed
84+
uint32_t _tls_min = BR_TLS10;
85+
uint32_t _tls_max = BR_TLS12;
7986
};
8087

8188
};

0 commit comments

Comments
 (0)