1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-24 08:45:10 +03:00
Earle F. Philhower, III f6dd826437
Fix MFLN probe and allow returning whether MFLN succeeded or not after a connection. (#6000)
Fixes #5996

* Add extensions to probe message for EC, others

probeMFLN was failing on some connection attempts to servers which only
supported EC based ciphers because it did not include the proper TLS
handshake extensions to list what kinds of ECs it supported.

Add those to the probeMFLN ClientHello message to make probes pass.

* Add client.getMFLNStatus method, returns MFLN state

After a connection it is useful to check whether MFLN negotiation
succeeded.  getMFLNStatus returns a bool (valid only after
client.connect() succeeds, of course) indicating whether the requested
buffer sizes were negotiated successfully.
2019-04-25 12:40:26 -07:00

138 lines
3.8 KiB
C++

// Shows how to use the Maximum Fragment Length option in
// BearSSL to reduce SSL memory needs.
//
// Mar 2018 by Earle F. Philhower, III
// Released to the public domain
#include <ESP8266WiFi.h>
#include <PolledTimeout.h>
#ifndef STASSID
#define STASSID "your-ssid"
#define STAPSK "your-password"
#endif
const char *ssid = STASSID;
const char *pass = STAPSK;
void fetch(BearSSL::WiFiClientSecure *client) {
client->write("GET / HTTP/1.0\r\nHost: tls.mbed.org\r\nUser-Agent: ESP8266\r\n\r\n");
client->flush();
using oneShot = esp8266::polledTimeout::oneShot;
oneShot timeout(5000);
do {
char tmp[32];
int rlen = client->read((uint8_t*)tmp, sizeof(tmp) - 1);
yield();
if (rlen < 0) {
break;
}
if (rlen == 0) {
delay(10); // Give background processes some time
continue;
}
tmp[rlen] = '\0';
Serial.print(tmp);
} while (!timeout);
client->stop();
Serial.printf("\n-------\n");
}
int fetchNoMaxFragmentLength() {
int ret = ESP.getFreeHeap();
Serial.printf("\nConnecting to https://tls.mbed.org\n");
Serial.printf("No MFLN attempted\n");
BearSSL::WiFiClientSecure client;
client.setInsecure();
client.connect("tls.mbed.org", 443);
if (client.connected()) {
Serial.printf("Memory used: %d\n", ret - ESP.getFreeHeap());
ret -= ESP.getFreeHeap();
fetch(&client);
} else {
Serial.printf("Unable to connect\n");
}
return ret;
}
int fetchMaxFragmentLength() {
int ret = ESP.getFreeHeap();
// Servers which implement RFC6066's Maximum Fragment Length Negotiation
// can be configured to limit the size of TLS fragments they transmit.
// This lets small clients, like the ESP8266, use a smaller memory buffer
// on the receive end (all the way down to under 1KB). Unfortunately,
// as of March 2018, there are not many public HTTPS servers which
// implement this option. You can deploy your own HTTPS or MQTT server
// with MFLN enabled, of course.
//
// To determine if MFLN is supported by a server use the
// ::probeMaxFragmentLength() method before connecting, and if it
// returns true then you can use the ::setBufferSizes(rx, tx) to shrink
// the needed BearSSL memory while staying within protocol limits.
//
// If MFLN is not supported, you may still be able to mimimize the buffer
// sizes assuming you can ensure the server never transmits fragments larger
// than the size (i.e. by using HTTP GET RANGE methods, etc.).
BearSSL::WiFiClientSecure client;
client.setInsecure();
bool mfln = client.probeMaxFragmentLength("tls.mbed.org", 443, 512);
Serial.printf("\nConnecting to https://tls.mbed.org\n");
Serial.printf("MFLN supported: %s\n", mfln ? "yes" : "no");
if (mfln) {
client.setBufferSizes(512, 512);
}
client.connect("tls.mbed.org", 443);
if (client.connected()) {
Serial.printf("MFLN status: %s\n", client.getMFLNStatus() ? "true" : "false");
Serial.printf("Memory used: %d\n", ret - ESP.getFreeHeap());
ret -= ESP.getFreeHeap();
fetch(&client);
} else {
Serial.printf("Unable to connect\n");
}
return ret;
}
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println();
Serial.println();
// We start by connecting to a WiFi network
Serial.print("Connecting to ");
Serial.print(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void loop() {
Serial.printf("\n\n\n\n\n");
yield();
int a = fetchNoMaxFragmentLength();
yield();
int b = fetchMaxFragmentLength();
yield();
Serial.printf("\n\n");
Serial.printf("Default SSL: %d bytes used\n", a);
Serial.printf("512 byte MFLN SSL: %d bytes used\n", b);
}