Preventing users from nuking their own firmware in a commercial product

Hello, all!

I'm heading up a project to put together prototypes of a device which my group is designing around the Teensy 4.1, and I'm writing here to solicit advice on the best way to go about safely integrating a Teensy (or at least the CPU which powers it) when/if the device goes to full production. As mentioned, the device will use either a real, physical Teensy 4.1 or a "virtual" Teensy - an i.MXRT1062 microcontroller paired with a Winbond flash memory chip and the MKL02 bootloader chip, all integrated into the PCB of our finished product.

As our finished device is likely to get new features and bug fixes down the road, we would like to make the "firmware" (merely the the code running on the embedded Teensy) easily upgradable by the end user. By design, our finished device will be left connected to the user's computer as part of its use, and the concern is that, if the user also happens to be programming an actual standalone Teensy of their own which they also have connected to their PC at the time, they may accidentally send their newly compiled sketch to the Teensy embedded in our product as opposed to the Teensy they intended to program. This would be a Very Bad Thing, and we want to eliminate the possibility of it happening. I seem to remember reading somewhere in the Teensy documentation that the bootloader only responds to automatic programming requests if an option is selected on the "USB Type" submenu of the Arduino IDE's "Tools" menu which includes "Serial". We will be using this serial port for some parts of our device's functionality, however, so it will need to remain enabled.

And thus, I'm wondering... is there any way to leave the Teensy bootloader in a "disabled" state by default so that it will not respond to incoming programming requests, but yet leave the basic functionality present so that the user may still easily update the code at a later date by re-enabling it temporarily? We definitely do not want our end users to feel that they need to disconnect our device each time they need to program their own microcontroller to avoid confusion, or have to press some kind of "disengage" button a'la the handy little device Paul made; the preferred way of dealing with this issue is to include a menu option in our product titled "Update firmware" which will allow the bootloader to accept incoming programming for a short time only to have that ability safely blocked once again after the Teensy reboots into the newly installed code.

I'm aware of the security features of the Teensy 4.1 which allow you to lock your code so that it cannot be extracted from the device, but that would also prevent people from updating the code later on (at least to my understanding - correct me if I'm wrong!) so it is not an option for our use case. I believe there are also fuses which can be set in the Teensy itself which will disable this function entirely, but that obviously is also not suitable for our needs.

If this is not possible, then I'm curious as to why. Is it only because some specific pin to allow doing so is simply not broken out onto the externally available pins of the Teensy? In other words, perhaps this would be technically possible when making your own PCB, but just cannot be done with the Teensy as it exists in its manufactured state. If that is the case, perhaps we would be better off simply using a "virtual" Teensy as mentioned above. Or, would it somehow help if we removed the bootloader entirely? Granted, we would then have to come up with some separate method of upgrading the firmware, but if we have to, we have to, I suppose.

On the topic of making your own Teensy-compatible, I did check out these links already:
https://www.pjrc.com/store/ic_mkl02_t4.html
https://forum.pjrc.com/threads/70978
https://forum.pjrc.com/threads/799-Firmware-loader-for-Teensy-3?p=1783&viewfull=1#post1783
https://forum.pjrc.com/threads/24063-Paul-Teensy-in-a-commercial-product?p=34451&viewfull=1#post34451
...but I'd still appreciate any tips or tricks that could be thrown my way by anyone who has already gone this route before, should this end up being the path we end up taking.

I'd love to hear any ideas with which you folks can come up, and thanks in advance!
 
The CORES code has code that monitors for bootloader request. Those could be made conditional and ignored by default on initial programming.

Some button(s) or USB input could be recognized to have the conditional pass (with a global variable value set) and allow the standard requests for bootloader to be entered for programming.

Using a lockable Teensy could work if the end user could have access to the needed .eHex properly encrypted. If code was provided only by you the end user could never program that device without the needed/exact key.pem file. If the end user has sources and expects to reprogram, they would have that key.pem file and any code they made would then be properly encrypted to an .eHex and nothing would stop it being uploaded through the normal means - unless 'hidden' as above. Once a lockable Teensy is locked it also prevents the 15 sec Restore button press that wipes the Teensy to factory blink.
 
The CORES code has code that monitors for bootloader request. Those could be made conditional and ignored by default on initial programming.

Some button(s) or USB input could be recognized to have the conditional pass (with a global variable value set) and allow the standard requests for bootloader to be entered for programming.

That sounds like a good way to go. Where exactly would I find the CORES code? I was browsing the Teensy 4 cores code on GitHub, but the cursory glance I've given it has not yet yielded any results.


Using a lockable Teensy could work if the end user could have access to the needed .eHex properly encrypted. If code was provided only by you the end user could never program that device without the needed/exact key.pem file. If the end user has sources and expects to reprogram, they would have that key.pem file and any code they made would then be properly encrypted to an .eHex and nothing would stop it being uploaded through the normal means - unless 'hidden' as above. Once a lockable Teensy is locked it also prevents the 15 sec Restore button press that wipes the Teensy to factory blink.

Indeed, we plan to be the only source for the firmware; the hardware will be open, but the software will likely not. Perhaps I need to read up on how the security model works on a locked Teensy.
 
To further explain, once locked in secure mode:

Only EHEX files created with your key.pem file can run. The hardware will not run ordinary HEX or any EHEX file created by a different key.

Access to erase the old firmware is only possible with a EHEX file created with your key.pem file. Without a proper EHEX file that matches the key you wrote into Teensy's fuse memory, pressing the button will cause Teensy to endlessly wait for Teensy Loader to begin communication with EHEX data. No erase or change to the existing firmware can happen without a proper EHEX file.

EHEX files are encrypted, so you can safely give them to untrusted people to perform the firmware update.

The flash chip is written with the same encrypted data as in the EHEX file, so an attacker can not capture your code by desoldering and inspecting the flash chip. Decryption happens on-the-fly entirely inside the IMXRT processor.

Locking secure mode turns on several hardware-level security features which are mentioned in the IMXRT1060 reference manual.

To get all this, you must write your key into fuse memory and then lock the hardware into secure mode by running the "Lock Security Sketch" code. If you write your key and use EHEX, the encryption alone is not secure. The hardware must be locked into secure mode for these security features to apply and for your code to have strong protection from copying or modification.
 
Regarding this question:

I'm aware of the security features of the Teensy 4.1 which allow you to lock your code so that it cannot be extracted from the device, but that would also prevent people from updating the code later on (at least to my understanding - correct me if I'm wrong!)

Here is the correction you requested! That assumption is indeed wrong.

You can update the code on Lockable Teensy after it's locked into secure mode.

More importantly, you can allow people you don't trust to update the code on Lockable Teensy after it's locked into secure mode. The security features are designed so you can safely give copies of the EHEX file to anyone and allow them to update hardware which is locked to secure mode.
 
@PaulStoffregen I really appreciate all that input! Indeed, I was just reading much of that on the page you linked, and it even appears that the MKL02 supports being locked into Secure Mode when bought separately so be used in a "virtual" Teensy. Sweet! This should address all of our concerns. Thank you!

One semi-related question... Is it possible to use the Teensy Loader in non-GUI mode or perhaps "skin" it so that it more closely matches our product when our end-users perform firmware updates?

Edit: Nevermind, I found the on the Teensy Loader Command Line app. Thanks for the help!
 
Last edited:
Back
Top