pycom / pycom-micropython-sigfox

A fork of MicroPython with the ESP32 port customized to run on Pycom's IoT multi-network modules.
MIT License
196 stars 167 forks source link

Request; Feature; Storing Crypto state to NVRAM #180

Open nevercast opened 5 years ago

nevercast commented 5 years ago

I'm developing sensors with the OEM LoPy, we've our first prototypes running and are very excited to finally have production ready boards after the R&D time spent, as for the firmware/software of our boards, we want our sensors to last a long time on battery in the field, we would also like to encrypt our LoRa traffic (We do not have a sufficient LoRaWAN infrastructure here in New Zealand yet). I have not tested my hypothesis yet but I assume that deep-sleep is going to kill the AES state (IV, Counter, etc), I would like a means of getting some of the AES state variables out of the crypto instance so that I can store them in NVRAM, then I can recreate my AES instance on wake.

My preference is having a function on the crypto instance along side decrypt and encrypt for .state() or .iv() or something similar. I would then use these values in the constructor of AES after waking up. I wish to use AES_CBC.

I'm happy to PR this work myself if we can agree on the implementation details, for another project that uses the WiPy I am maintaining many patch files that we apply to the firmware after each update from Pycom and I'd like to minimize my patch file work load by getting this functionality directly in to upstream.

Looking forward to discussing this feature.

Clarification

The (above) post was not sufficiently clear the first time I posted, here is more information.

I wish to use CFB in streaming mode, where the IV is manipulated each time the cipher is used. My understanding is that if I use one instance of AES to encrypt, and one instance to decrypt, provided they are initialized with the same IV, their IVs will update each time an encrypt and decrypt operation occurs. Provided that the ciphertext and plaintext are not corrupted during transmit (I've a CRC16 to validate this), the two instances will remain in sync as far as IV goes, so the decrypt instance will continue to decipher the encrypt instance.

This allows me to have an always-on gateway over LoRa that keeps the IV of the remote node in sync, without having to send a new IV over the air every block.

You can see a demonstration of how the IV becomes a component of the ciphertext from NIST, here: (See figures at the end of the document) https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf

The Pycom docs here: https://docs.pycom.io/chapter/firmwareapi/pycom/aes.html say the implementation is NIST compliant, and I know it is using the ESP32 sdk for this, which does state that the IV is updated as expected: http://esp32.info/docs/esp_idf/html/d5/dbb/esp32_2include_2hwcrypto_2aes_8h.html#a32883a530f294795cddd0c8b9e9096e6

I wish to be able to retrieve these intermediate values so they can be stored in NVRAM during deep-sleep. image

The ESP32 docs say this value is applied to the parameter iv[16] which is stored in a union field in the mp_obj_AES_t object inside your ucrypto module.

Kind regards, Josh. Brush Technology.

iwahdan88 commented 5 years ago

Hi Josh,

It is not recommended to reuse IV data , For every message encrypted with the same key a different IV should be used as it is mentioned in pycom documentation.

To avoid security issues, IV should always be a random number and should never be reused to encrypt two different messages. The same applies to the counter in CTR mode. You can use crypto.getrandbits() for this purpose.

I am afraid we cannot add this functionality as it may introduce security issues.

nevercast commented 5 years ago

The IV would not be the same in CFB and CBC modes because the specification for these modes updates the IV as an output parameter, so that these modes can be used in streaming functionality. I would like to still use the streaming functionality but across deep-sleep.

See the note in the ESP32 spec. http://esp32.info/docs/esp_idf/html/d5/dbb/esp32_2include_2hwcrypto_2aes_8h.html#a5e7142edb96781127774244ae902551c

The IV will remain the same on both ends of the transaction in streaming mode since the new IV is generated based on the ciphertext, this means the IV needs to be sent for the first packet and not thereafter; this reduces 16 bytes from my LoRa payload which reduces my duty cycle of on time, and I believe it also aids my security by keeping my IV out of the public.

I'm fairly certain this information I've presented is correct and secure. But if you know a security professional they can certainly weigh in on this.

I've updated my original post to spare other developers the effort of scrolling to this comment.