WiFiServerSecure: Cache SSL sessions#7774
Merged
earlephilhower merged 9 commits intoesp8266:masterfrom Dec 22, 2020
Merged
Conversation
earlephilhower
requested changes
Dec 19, 2020
Collaborator
earlephilhower
left a comment
There was a problem hiding this comment.
Thanks, this looks like a great addition! Just a minor API request, please.
earlephilhower
approved these changes
Dec 20, 2020
Collaborator
earlephilhower
left a comment
There was a problem hiding this comment.
Thanks for the update.
LGTM and seems very useful!
Contributor
Author
|
No problems! It's always a pleasure to contribute to this repository |
davisonja
added a commit
to davisonja/Arduino
that referenced
this pull request
Dec 28, 2020
…lash * upstream/master: (72 commits) Typo error in ESP8266WiFiGeneric.h (esp8266#7797) lwip2: use pvPortXalloc/vPortFree and "-free -fipa-pta" (esp8266#7793) Use smarter cache key, cache Arduino IDE (esp8266#7791) Update to SdFat 2.0.2, speed SD access (esp8266#7779) BREAKING - Upgrade to upstream newlib 4.0.0 release (esp8266#7708) mock: +hexdump() from debug.cpp (esp8266#7789) more lwIP physical interfaces (esp8266#6680) Rationalize File timestamp callback (esp8266#7785) Update to LittleFS v2.3 (esp8266#7787) WiFiServerSecure: Cache SSL sessions (esp8266#7774) platform.txt: instruct GCC to perform more aggressive optimization (esp8266#7770) LEAmDNS fixes (esp8266#7786) Move uzlib to master branch (esp8266#7782) Update to latest uzlib upstream (esp8266#7776) EspSoftwareSerial bug fix release 6.10.1: preciseDelay() could delay() for extremely long time, if period duration was exceeded on entry. (esp8266#7771) Fixed OOM double count in umm_realloc. (esp8266#7768) Added missing check for failure on umm_push_heap calls in Esp.cpp (esp8266#7767) Fix: cannot build after esp8266#7060 on Win64 (esp8266#7754) Add the missing 'rename' method wrapper in SD library. (esp8266#7766) i2s: adds i2s_rxtxdrive_begin(enableRx, enableTx, driveRxClocks, driveTxClocks) (esp8266#7748) ...
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
WiFiClientSecure::setSessionallows users to use a feature in BearSSL to cache the SSL session to a server.BearSSL also allows caching SSL session on the server side, therefore I've created the method
WiFiServerSecure::setCacheto allow the user to setup a cache allowing BearSSL to resume the SSL sessions of client and greatly shorten the length of TLS handshakes.Here are the steps that I have followed when implementing this feature:
ESP8266WiFilibraryESP8266WiFilibrarykeywords.txtfileESP8266WiFilibrary (I've chosen the BearSSL_Server example)ESP8266WebServerlibrary (I've chosen the HelloServerBearSSL example)If you want to test this feature, I encourage you to use these examples and to enable and disable the cache to see the performance improvements. In order to reset the server's cache, you simply have to reset the microcontroller.
Testing the examples
Here's a ruby script that I've written to test the performance improvements that this PR is bringing. It does 100 requests using a new SSL session each time and 100 more using the same session.
Results
I've used this script to test the BearSSL_Server and HelloServerBearSSL examples before, after this PR without the cache activated and after this PR with the cache activated. For BearSSL_Server, I did the test once with the RSA key and another time with the EC key.
BearSSL_Server with the RSA key
Before the PR
After the PR without caching
After the PR with caching
Summary
The improvement ratio is the time of
Don't reuse the sessionover the time ofReuse the session.BearSSL_Server with the EC key
Before the PR
After the PR without caching
08:54:58 PM user system total real don't reuse session: 0.339462 0.088985 0.428447 ( 36.511242) reuse session: 0.320082 0.097038 0.417120 ( 37.105757)After the PR with caching
Summary
The improvement ratio is the time of
Don't reuse the sessionover the time ofReuse the session.HelloServerBearSSL
Before the PR
After the PR without caching
After the PR with caching
Summary
The improvement ratio is the time of
Don't reuse the sessionover the time ofReuse the session.Analysis
Those numbers show that this PR makes the HTTPS requests about 25x faster with an RSA key and 6x with an EC key when caching is enabled. When caching isn't enabled, this PR doesn't seem to negatively affect performance at all.
We can see that BearSSL_Server is faster than HelloServerBearSSL and its improvement is greater, because this PR only improves the TLS handshake, so the longer the server takes to parse the request and create a response, the less improvement there is and HelloServerBearSSL implements a web server which is slower than BearSSL_Server that answers all requests with the same response without parsing them.
It is to be noted that, in the script that reuses the session, the time of the first request of the session isn't counted because this PR doesn't improve it.
Testing the TLS handshake improvement
The previous test was testing the speed improvement for the full HTTP request, but this PR should only improves the TLS handshake.
In order to see it I've tested the BearSSL_Server with an RSA and an EC key using Firefox's network timing analyzer.
This test is a little less rigourous, because I didn't do it 100 times like the others, but it allows us to see the improvement for each part of the request.
RSA key
Before the PR
After the PR without caching
After the PR with caching
First request:

All subsequent requests:

Summary
The improvement is the measure before the PR over the current measure.
EC key
Before the PR
After the PR without caching
After the PR with caching
First request:

All subsequent requests:

Summary
The improvement is the measure before the PR over the current measure.
Analysis
These numbers show the same thing as the previous tests: this PR greatly improves the speed of cached requests and doesn't have any noticeable downside.
However, this test shows clearly shows how much the TLS handshake is a bottleneck without this PR and how much it's improved when the server caches the client's sessions.
Somehow it also slightly improves the waiting time for the server response. I don't think it means that the server decrypts the request faster or processes it faster in any way. I simply think that this is because when resuming cached sessions the client ends the handshake instead of the server. This means that the client can start sending the application data at the same time as it sends the TLS record to end the handshake. This would therefore reduce the time the client has to wait for the server response.
You can see this at page 35 and 36 of the TLS 1.2 standard:
Client Server ClientHello --------> ServerHello Certificate* ServerKeyExchange* CertificateRequest* <-------- ServerHelloDone Certificate* ClientKeyExchange CertificateVerify* [ChangeCipherSpec] Finished --------> [ChangeCipherSpec] <-------- Finished Application Data <-------> Application Data Figure 1. Message flow for a full handshakeClient Server ClientHello --------> ServerHello [ChangeCipherSpec] <-------- Finished [ChangeCipherSpec] Finished --------> Application Data <-------> Application Data Figure 2. Message flow for an abbreviated handshakeConclusion
This PR doesn't seem to have any negative performance impact, only positive ones. Once enabled by the user, it will increase performance of cached sessions by 20 to 25 times depending the type of encryption used. The slower the encryption is, the more this feature will boost performances. However, users need to be well aware that the TLS client they're using also needs to cache the session in order to experiment this performance boost. This is why it was clearly mentionned in the documentation.