Skip to content

Commit aa476cf

Browse files
Allow cipher specification for BearSSL
BearSSL has many more ciphers than axTLS, but they are more compute intensive and slower. Add an option to use only the same, limited security, axTLS ciphers as well as allow users to specify any suite of ciphers they want using standard BearSSL formats. Fixes esp8266#5110
1 parent 1a44f79 commit aa476cf

File tree

3 files changed

+53
-5
lines changed

3 files changed

+53
-5
lines changed

libraries/ESP8266WiFi/examples/BearSSL_Validation/BearSSL_Validation.ino

+20
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,25 @@ BearSSL does verify the notValidBefore/After fields.
193193
fetchURL(&client, host, port, path);
194194
}
195195

196+
void fetchAxTLS() {
197+
Serial.printf(R"EOF(
198+
The ciphers used to set up the SSL connection can be configured to
199+
be the same as axTLS. They are faster, but less secure, so if you care
200+
about security you won't want to do this.
201+
)EOF");
202+
BearSSL::WiFiClientSecure client;
203+
client.setInsecure();
204+
uint32_t now = millis();
205+
fetchURL(&client, host, port, path);
206+
uint32_t delta = millis() - now;
207+
now = millis();
208+
client.setInsecure();
209+
client.setAxTLSCiphers();
210+
fetchURL(&client, host, port, path);
211+
uint32_t delta2 = millis() - now;
212+
Serial.printf("Using more secure: %dms\nUsiing axTLS ciphers: %dms\n", delta, delta2);
213+
}
214+
196215
void setup() {
197216
Serial.begin(115200);
198217
Serial.println();
@@ -220,6 +239,7 @@ void setup() {
220239
fetchSelfSigned();
221240
fetchKnownKey();
222241
fetchCertAuthority();
242+
fetchAxTLS();
223243
}
224244

225245

libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp

+23-4
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ void WiFiClientSecure::_clearAuthenticationSettings() {
8585

8686

8787
WiFiClientSecure::WiFiClientSecure() : WiFiClient() {
88+
_cipher_list = NULL;
89+
_cipher_cnt = 0;
8890
_clear();
8991
_clearAuthenticationSettings();
9092
_certStore = nullptr; // Don't want to remove cert store on a clear, should be long lived
@@ -685,6 +687,13 @@ extern "C" {
685687
BR_TLS_RSA_WITH_3DES_EDE_CBC_SHA
686688
};
687689

690+
// For apps which want to use less secure but faster axTLS ciphers, only
691+
static const uint16_t axtls_suites_P[] PROGMEM = {
692+
BR_TLS_RSA_WITH_AES_256_CBC_SHA256,
693+
BR_TLS_RSA_WITH_AES_128_CBC_SHA256,
694+
BR_TLS_RSA_WITH_AES_256_CBC_SHA,
695+
BR_TLS_RSA_WITH_AES_128_CBC_SHA };
696+
688697
// Install hashes into the SSL engine
689698
static void br_ssl_client_install_hashes(br_ssl_engine_context *eng) {
690699
br_ssl_engine_set_hash(eng, br_md5_ID, &br_md5_vtable);
@@ -705,9 +714,9 @@ extern "C" {
705714
}
706715

707716
// Default initializion for our SSL clients
708-
static void br_ssl_client_base_init(br_ssl_client_context *cc) {
709-
uint16_t suites[sizeof(suites_P) / sizeof(uint16_t)];
710-
memcpy_P(suites, suites_P, sizeof(suites_P));
717+
static void br_ssl_client_base_init(br_ssl_client_context *cc, const uint16_t *cipher_list, int cipher_cnt) {
718+
uint16_t suites[cipher_cnt];
719+
memcpy_P(suites, cipher_list, cipher_cnt * sizeof(cipher_list[0]));
711720
br_ssl_client_zero(cc);
712721
br_ssl_engine_set_versions(&cc->eng, BR_TLS10, BR_TLS12);
713722
br_ssl_engine_set_suites(&cc->eng, suites, (sizeof suites) / (sizeof suites[0]));
@@ -726,6 +735,12 @@ extern "C" {
726735

727736
}
728737

738+
// Set the AXTLS ciphers as the only ones allowed
739+
void WiFiClientSecure::setAxTLSCiphers()
740+
{
741+
setCiphers(axtls_suites_P, sizeof(axtls_suites_P)/sizeof(axtls_suites_P[0]));
742+
}
743+
729744
// Installs the appropriate X509 cert validation method for a client connection
730745
bool WiFiClientSecure::_installClientX509Validator() {
731746
if (_use_insecure || _use_fingerprint || _use_self_signed) {
@@ -787,7 +802,11 @@ bool WiFiClientSecure::_connectSSL(const char* hostName) {
787802
return false;
788803
}
789804

790-
br_ssl_client_base_init(_sc.get());
805+
// If no cipher list yet set, use defaults
806+
if (_cipher_list == NULL) {
807+
setCiphers(suites_P, sizeof(suites_P) / sizeof(uint16_t));
808+
}
809+
br_ssl_client_base_init(_sc.get(), _cipher_list, _cipher_cnt);
791810
// Only failure possible in the installation is OOM
792811
if (!_installClientX509Validator()) {
793812
_freeSSL();

libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.h

+10-1
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,17 @@ class WiFiClientSecure : public WiFiClient {
104104
_certStore = certStore;
105105
}
106106

107+
// Select specific ciphers (i.e. optimize for speed over security)
108+
// These may be in PROGMEM or RAM, either will run properly
109+
void setCiphers(const uint16_t *cipherAry, int cipherCount) { _cipher_list = cipherAry; _cipher_cnt = cipherCount; }
110+
void setAxTLSCiphers(); // Only use the limited set of axTLS ciphers
111+
107112
// Check for Maximum Fragment Length support for given len
108113
static bool probeMaxFragmentLength(IPAddress ip, uint16_t port, uint16_t len);
109114
static bool probeMaxFragmentLength(const char *hostname, uint16_t port, uint16_t len);
110115
static bool probeMaxFragmentLength(const String host, uint16_t port, uint16_t len);
111116

112-
// AXTLS compatbile wrappers
117+
// AXTLS compatible wrappers
113118
bool verify(const char* fingerprint, const char* domain_name) { (void) fingerprint; (void) domain_name; return false; } // Can't handle this case, need app code changes
114119
bool verifyCertChain(const char* domain_name) { (void)domain_name; return connected(); } // If we're connected, the cert passed validation during handshake
115120

@@ -170,6 +175,10 @@ class WiFiClientSecure : public WiFiClient {
170175
const BearSSLPublicKey *_knownkey;
171176
unsigned _knownkey_usages;
172177

178+
// Custom cipher list pointer or NULL if default
179+
const uint16_t *_cipher_list;
180+
uint16_t _cipher_cnt;
181+
173182
unsigned char *_recvapp_buf;
174183
size_t _recvapp_len;
175184

0 commit comments

Comments
 (0)