Experiences with encryption on Teensy

Status
Not open for further replies.

iwanders

Well-known member
This post started as a reply to the forum post "Teensy as secure storage for private keys", and this remark posted by cr7pt0:
... My next step is to incorporate AES or ECC functionality but I have not found a good library yet so suggestions would be appreciated.
I started typing a reply to this but then realized it would probably be better to make a separate post for this instead of hijacking the thread. This is not really a question, just me sharing my experiences in this regard and perhaps providing you all with some useful information. It is a bit heavy on the links and I assumed some knowledge of cryptography.

Over the past years I have worked on-and-off on a framework to network Teensy microcontrollers, I intended to use radio communication, which is susceptible to eavesdropping and manipulation. As I use this network to control lighting and transmit sensor values or even actuate things in the future I put security very high on the priority list. I wanted three things; encryption, authentication and protection against replay attacks.

I started with NRF24 radio modules and briefly used a handshake which was more or less the following: use a pre-shared secret, both parties sent a nonce to each other and hashed the three values this output was used a cipher key, paired with the Rabbit stream cipher (this implementation). This worked, but eventually I didn't really like the handshake because it didn't seem all that elegant. I looked for alternatives, I encountered Curve25519 and the reference implementation http://cr.yp.to/ecdh.html (edit; I meant http://code.google.com/p/curve25519-donna/. This was quite easy to get up and running on the Teensy 3.0, basically just include the reference implementation and copy the 'usage' section from the readme. I just reran my tests and my Teensy 3.1 runs the curve25519_donna step in 168 ms at 48 MHz, and 90 ms at 96MHz, more than fast enough for my applications. So if you want ECDH, I recommend you give this a shot.

However, one problem of this was that the NRF24 radio modules needed several packets to transmit the public secrets required for this handshake, I was also unsatisfied by the reliability of the radio modules, even with a software-retry mechanism in place the performance was below my expectations (perhaps due to the NRF24's being counterfeits?). Somewhere at this time I also realized it would be so much easier if I had a stateless encryption scheme, at this time I switched to the RFM69 radios. These can send packets of up to 64 bytes and offer hardware AES encryption. It was my intention to use this encryption back then, with a nonce (and counter) in the header I could rule out replay attacks. However, I quickly ran into a problem; when writing my own library I figured out that this radio uses ECB cipher mode (analysis here). I refer you to read to the wikipedia page for an explanation why this is a big no-no, I tried to fix this problem by inserting a nonce in each 16 byte block, but that would've resulted in too many lost bytes to overhead. Also, this felt like a band-aid and a violation of the commonly shared opinion that 'you should not implement your own cryptography scheme' (a post from Schneier on this).

So all of this brought me back to the drawing board. What I wanted was pretty simple; encryption, authentication and protection against replay-attacks. So I did more research, eventually a friend told me about a technique called authenticated encryption, which would allow me to swat two flies in one fell swoop; These wikipedia pages; Block cipher modes - Authenticated encryption and Authenticated encryption provide explanation. After more reading I singled out the OCB authenticated encryption (more info: RFC7253 - OCB3). This is authenticated encryption scheme is based on AES, it is required to use a 12 byte nonce and it results in a ciphertext and tag (128, 96 or 64 bit) used for authentication. The implementation I used was the reference implementation (the optimized one), it uses the 'rijndael-alg-fst' public domain implementation of AES. This AES implementation worked without any modifications for Teensy, so if you are looking for a ready to use AES implementation, try this one.

Using the OCB3 scheme I created a class called SecureMessenger which handles the encryption, decryption and keeping track of the counters seen from various origins. I use a header of 16 bytes, then 32 bytes of data and a 16 byte tag, allowing me to transmit 32 bytes of data in one packet using the RFM69 radio. Still an overhead of 32 bytes, but this provides both the encryption, authentication and replay attack protection. I store the counters which are used in the nonces in the EEPROM of the Teensy, specifically I increment the major counter at boot and the minor counter is incremented when a message is sent.

In my opinion, in the DIY community encryption is often seen as something that solves all security problems. However it does not guard against replay attacks, and when used wrongly such as in ECB it does not guard against tampering with the data either. With radio modules such as the RFM69's it is trivial to record a message and retransmit it later, so protection against this kind of attacks has to be done on the software level. Less important of course if you just control your lighting, more so if you are opening your garage door with them. Judging by the level of discussions about security the Teensy community appears to be more concious of all of this, which is one of the reasons I took the time to write this post. I hope this detail of my efforts and experiences will be helpful to someone. Disclaimer: I am by no means an expert on cryptography. I have spent quite some time reading about it out of interest, but I still expect the system I now use to have flaws. If you are going to do something important, please consult an expert.

TL;DR, just to answer cr7pt0's question:
Elliptic Curve Diffie-Helman: Curve25519 and the reference implementation: http://cr.yp.to/ecdh.html, edit; I meant this one: http://code.google.com/p/curve25519-donna/
AES: Public domain implementation called 'rijndael-alg-fst, for example from: rijndael-alg-fst.c rijndael-alg-fst.h.
 
Last edited:
The IEEE 802.15.4 smart radios, such as Digi International's XBee SERIES 1 (not equivalent to their series 2) has AES128 per the IEEE 802.15.4 standard built in. These modules also have data acquisition and virtual wire (GPIO in/out) built in. So many projects can use the XBee and no additional microprocessor.

A large project I did used XBee S1 but needed part of the payload unencrypted (a header). 802.15.4 can't do that; it's all or nothing. Also, I had to have a nonce and unique key per device so that if a field device were stolen, others are unaffected. This was an extreme example - most wireless SCADA and sensor systems can use a rarely changing shared key as in 802.15.4.

My comment here is that the 100 byte payload max for small and low cost radios like the XBee and the HopeRF FM/GFSK sub-GHz radios, can readily be done using AES128 + CCM (per NIST) but with the option of block truncation so as to avoid wasting some of the 100 bytes due to a fixed block size. The compute time per payload frame, on a 72MHz ARM7, was about 1-2 mSec.

With small payload size limits, one cannot use PC class encryption such as SSL or AES256 and one should not use AES128 generic rather than CCM/Block truncation.

You could encrypt using AES128 CCM block truncation on the host microprocessor.. this is payload content; it's independent of the transport protocol (standard or bespoke). The payload is then given to the wireless MAC and PHY (such as the XBee w/802.15.4 with its MAC layer encryption off.). At the receiving end, I took the still encrypted payload verbatim and copied it to an Ethernet IP packet (bridging). The bridge did not have the key to decrypt. So the bridge need not be in the trusted base, and can be unattended (outdoors for wireless coverage). The addressee of the IP packet did have the key and sync'd nonce and can decrypt. Over the air re-keying was done using a special and different key and different nonce. These diminished the risk of man-in-the-middle, replay, and system-wide compromise since a shared key was not used.
 
Last edited:
iwanders - Thanks for the detailed response and information provided this is very helpful. I don't have much experience with radio, other than wifi hacking. I would think that if your using pre-shared keys AES CCM or GCM would work good for confidentiality and authentication. You could easily attach one of these via I2C to the teensy if you want to do encryption in HW - http://www.atmel.com/devices/ATAES132A.aspx

For my project I was wanting to make something that was physically as secure as you can get that secures the root key, and then use already well tested algorithms such as AES and ECC (Curve25519) and additionally keys that are encrypted with the root key. So for example if you had a radio you could add my project to the radio to secure the keys from physical attack. If the radio is lost or stolen keys would not be compromised. I wrote more on the threat model in the other thread we started on. My project could also be used as a bitcoin wallet or a hardware token. I was able to get Yubikey code running on the Teensy and use the capacitive touch sensors as the button to press for the OTP - https://github.com/cr7pt0/TeensyKey

Would you be able to share the code you used for Curve25519 on the Teensy? I tried to get this working but so far have not been able to due to my severely lacking programming skills. I was able to use the uECC library https://github.com/kmackay/micro-ecc but right now this only supports 5 curves - secp160r1, secp192r1, secp224r1, secp256r1, and secp256k1. I also have messed around with Curve25519 using details from http://munacl.cryptojedi.org/curve25519-cortexm0.shtml But have not gotten this working on Teensy. I did buy a STM32F0Discovery development board that I was going to try to figure out first but have not done that yet.

Also I found some info on AES libraries that would work with Teensy but I really want one that supports AES 256 in CCM or GCM mode. Here is one that supports AES 128 in CBC mode https://github.com/DavyLandman/AESLib.
 
Would you be able to share the code you used for Curve25519 on the Teensy?
Sure. Upon looking close at the code I realised I referenced the wrong source of the algorithm I used. The implementation I used was from http://code.google.com/p/curve25519-donna/. You can just include or copy paste the curve25519-donna.c file from that project. Attached is the file I used to measure the durations. It's not in the Arduino setup() and loop() style though, it has a main function with a while(true) loop in it, line 4 to 600 is curve25519-donna.c, the last 50 lines are executing it and printing. I hope it is clear enough: View attachment main.cpp.

Also I found some info on AES libraries that would work with Teensy but I really want one that supports AES 256 in CCM or GCM mode.
You're probably best off looking for a generic C implementation, the Teensy is quite a capable platform and I don't think you have to look for microcontroller specific implementations. Though you might have to add the PROGMEM keyword to lookup tables to prevent running into RAM limitations.
 
You're probably best off looking for a generic C implementation, the Teensy is quite a capable platform and I don't think you have to look for microcontroller specific implementations. Though you might have to add the PROGMEM keyword to lookup tables to prevent running into RAM limitations.
On the Teensy 3.0/3.1/3.2/LC, you don't need PROGMEM to force the lookup tables into read-only memory. You just need to use the const keyword in the declaration, and the compiler/linker will move the tables into read-only flash memory. This is due to the ARM having a unified memory system. On AVR based systems like the Teensy 2.0/2.0++, you do need to use PROGMEM to put the data into flash memory, and use accessor functions to read a particular element.
 
NIST's web site has example C code.
Most importantly, they have implementation verification software and data. With that, you input their data to your implementation. You compare your encrypted output to their reference data (byte by byte).
There's also the issue of using the same nonce (if applicable).

Unless you use CCM w/block truncation, an AES option (maybe only AES128), the output will have padding bytes to fill out the final block. With small sized payloads limits in, e.g., telemetry type data radios, CCM is important for encryption at the application layer for end-to-end (across 2+ networks), rather than MAC layer encryption (1 hop only, then man in the middle or a 'trusted' bridge).
 
Last edited:
Does this piece of SPI or I2C interface EEPROM storage hardware offer any useful features? Not a complete solution - but a set of hardware based helpers and 32Kbit secure storage for $1.07.

Atmel ATAES132A-SHEQ-T .

 Crypto Element Device with Secure Hardware-based Key Storage
 32Kb Standard Serial EEPROM Memory
 Compatible with the Atmel® AT24C32D and the Atmel AT25320B
 16 User Zones of 2Kb Each
 High-security Features
 AES Algorithm with 128-bit Keys
 AES-CCM for Authentication
 Message Authentication Code (MAC) Capability
 Secure Storage for up to Sixteen 128-bit Keys
 Encrypted User Memory Read and Write
 Internal High-quality FIPS Random Number Generator (RNG)
 16 High-Endurance Monotonic EEPROM Counters
 Flexible User Configured Security
 User Zone Access Rights Independently Configured
 Authentication Prior to Zone Access
 Read/Write, Encrypted, or Read-only User Zone Options
 High-speed Serial Interface Options
 10MHz SPI (Mode 0 and 3)
 1MHz Standard I2C Interface
 
Definitely cool to know that such parts exist. Whether those IC's are useful depends on your use-case I guess, I wanted to keep the complexity low (so without external components). You can probably use it quite easily to encrypt and authenticate packets for use in radio communication, it seems to be well suited for that with the secure counters and authentication methods. I knew there were IC's which helped with cryptography, but didn't know that they offered such extensive features, thanks for sharing.

@MichaelMeissner; Thank you for the explanation on the const/PROGMEM keyword, I learned something new there :)
 
Hi ,
Just tried the AES128 lib with Teensy3.1 :
"Here is one that supports AES 128 in CBC mode https://github.com/DavyLandman/AESLib."

With the Davy Landman's code:----------------------
#include <AESLib.h>

void setup()
{

uint8_t key[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
Serial.begin(57600);
char data[] = "0123456789012345"; //16 chars == 16 bytes
aes128_enc_single(key, data);
Serial.print("encrypted:");
Serial.println(data);
aes128_dec_single(key, data);
Serial.print("decrypted:");
Serial.println(data);
}

void loop() {}
----------------------------------------
It appears to compile for Arduino, but for Teensy3.x I get following errors:
c:\program files (x86)\arduino\hardware\teensy\avr\cores\teensy3\core_pins.h:1326: Error: junk at end of line, first unrecognized character is `}'
c:\program files (x86)\arduino\hardware\teensy\avr\cores\teensy3\core_pins.h:1327: Error: bad instruction `if (val){'
c:\program files (x86)\arduino\hardware\teensy\avr\cores\teensy3\core_pins.h:1328: Error: junk at end of line, first unrecognized character is `*'
c:\program files (x86)\arduino\hardware\teensy\avr\cores\teensy3\core_pins.h:1329: Error: junk at end of line, first unrecognized character is `}'
c:\program files (x86)\arduino\hardware\teensy\avr\cores\teensy3\core_pins.h:1330: Error: junk at end of line, first unrecognized character is `*'
c:\program files (x86)\arduino\hardware\teensy\avr\cores\teensy3\core_pins.h:1331: Error: junk at end of line, first unrecognized character is `}'
c:\program files (x86)\arduino\hardware\teensy\avr\cores\teensy3\core_pins.h:1332: Error: junk at end of line, first unrecognized character is `}'
c:\program files (x86)\arduino\hardware\teensy\avr\cores\teensy3\core_pins.h:1333: Error: junk at end of line, first unrecognized character is `}'
.
.
.
many such errors.

Maybe there is something basic missing in the above code?
Has anyone successfully compiled the above library for Teensy3 ?

Help?

Thanks in advance
 
That library is full of AVR-specific assembly code, that is not going to work on the Teensy 3 with it's ARM chip. I am not familiar with a library that runs on Teensy that provides the CBC ciphermode with AES out of the box (anyone else?). (You could just implement the CBC cipher mode with the rijndael-alg-fst AES code I mentioned and thoroughly test it with test vectors.)
 
I've implemented XTEA-128-CBC and use an incremental IV and a static key. I use it for transmission between to Teensy controllers via an APC220 wireless serial modem.
 
I understand that there is currently no library for the hardware cipher accelerator for TEENSY 4.0.
Also, the "i.MX RT1060 Processor Reference Manual" of NXP does not give details about the security components of the chip's co-processor.
I suspect that these details are in the "Security Reference Manual for the i.MX RT106x Processor" which is locked.
How can I get access to this information, in order to access the chip's AES-128 unit?
 
Status
Not open for further replies.
Back
Top