Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Best place to store AWS IoT client private_key+certificate? #5860

Closed
s-hadinger opened this issue May 25, 2019 · 4 comments · Fixed by #6179
Closed

Best place to store AWS IoT client private_key+certificate? #5860

s-hadinger opened this issue May 25, 2019 · 4 comments · Fixed by #6179
Labels
good tip Type - Very useful information question Type - Asking for Information

Comments

@s-hadinger
Copy link
Collaborator

Apologies if it’s the wrong place to discuss a development question.

I’m reviving an old topic: connecting Tasmota to AWS IoT for remote MQTT, and still using Web/Hue Emulation.

I've been working on it for the last weeks and I have a working prototype using as low 6.3KB of heap memory in nominal state (+ 1KB of stack), and an additional transient 8.0KB during TLS handshake (connect or reconnect). TLS handshake takes 1.3s at 80MHz or 0.7s at 160MHz.

Here is my question:

Each device needs to have a distinct TLS Private Key and Certificate. They can be in string (PEM) format but would ideally be stored as binary format to spare some decoding code. Size is ~1.5KB. What would be the best option to store them?

  1. Custom compile each firmware with key burnt in it?
  2. Would it make sense to burn a 4KB PROGMEM zone, and use spi_flash_write to update this Flash block? Did somebody already do this?
  3. SPIFFS? But I know we don't have SPIFFS on Tasmota

For the curious:

For the curious, here are some implementation details about memory optimization.

It is now possible to have both Web/Hue and TLS because of the following (see #2031)

  1. Web interface now uses chunks (thanks @arendst), hence a reduced need for heap memory.
  2. Arduino moving from AXTLS to BearSSL, it allows to dramatically reduce RAM requirements.

Even if BearSSL use little memory, the stock WifiSecureClient takes at least 18KB of heap.
I was able to aggressively reduce the memory requirements:

  • MFLN support. Normal SSL/TLS requires 16KB buffers – which is huge for an ESP8266. Fortunately AWS IoT supports TLS1.2 and MFLN (Max Fragments Length). MFLN allows to reduce send/receive buffers to 2x1024 bytes. Note: using 512 bytes buffers causes packet drops and very slow TLS handshake.
  • Elliptic Curve (EC) Private Key. Default Private Key in AWS IoT uses RSA 2048 bits keys. Switching to EC 256 bits key saves a lot of space, for increased security and slightly faster handshake.
  • ECDHE_RSA_WITH_AES_128_GCM_SHA256 cipher. To save code and RAM, it only supports the previous algorithm. ECDHE with EC key, RSA certificate on server side, AES 128 which is 40% faster than AES256, GCM instead of CBC.
  • Fingerprint validation. The server certificate is not validated against the CA. Instead there are two options: either ignore server certificate (not super secure), or learn fingerprint of first connection. The fingerprint is calculate on the server’s public key instead of certificate, this is more robust in case of a certificate renewal of the server with the same public key.
  • Custom Thunk Stack. Arduino uses a secondary stack of 5.6KB mainly used during handshake. Instead of constantly using this memory, it is only allocated during handshake. For normal TLS communication after handshake, AES GCM 128 does not need more than 1KB, so the normal ESP8266 stack is enough.
  • P256 curve. To save code size , it only supports the P256 elliptic curve.
@Jason2866
Copy link
Collaborator

  1. would be easiest no change in code. Doing like letsencrypt via add define.. (sonoff_letsencrypt.h)
  2. maybe via EEPROM (see settings.ino)
  3. I think this break compatibility?

@arendst
Copy link
Owner

arendst commented May 26, 2019

Tasmota currently uses all flash space made available by the Arduino core library within a 1MB image.

As flash is accessesed in 4k chunks minimal this leads to Image flash adresses from 00xxx to FFxxx. To serve OTA images as large as possible it temporarly moves the settings area to location FB000 used by the Arduino core library for EEPROM data. Pages FC to FF are being used by the SDK.

If you make a dump of the flash area from FC to FF (4 pages) you'll noticed that a lot of space doesn't seem to be used.

If you are adventurous you could try to use 1k5 of a 4k SDK page for the TLS private Key and certificate. Accessing page FC is probably problematic as the Arduino core library simulates this page with dedicated settings. You might want to try page FF which only seems to use the first 32 bytes...

Any other flash location would reduce OTA file.

@ascillato2 ascillato2 added good tip Type - Very useful information question Type - Asking for Information labels May 26, 2019
@s-hadinger
Copy link
Collaborator Author

Thanks @arendst
For now I'll stay in solution (1) custom compile with key burnt in firmware. I'll keep the adventure for later.
Btw, if I encode as pure binary form, I can go down to ~800 bytes.

@s-hadinger
Copy link
Collaborator Author

@arendst Thanks for the excellent suggestion. I tried using page FF and it works like a charm. I'm storing the credentials (~800 bytes) from location 0x402FF400 to 0x402FF7FF.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good tip Type - Very useful information question Type - Asking for Information
Projects
None yet
4 participants