Protecting MicroPython source code and DFU updates

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
User avatar
Dugite
Posts: 21
Joined: Thu Jan 18, 2018 1:29 pm

Protecting MicroPython source code and DFU updates

Post by Dugite » Sat Jun 08, 2019 12:54 am

I have developed a commercial product using the Pyboard 1.1 MicroPython for the base design (new PCB is currently being manufactured).

I am now looking at how to best achieve the following for source code protection (which I know is not a 100% guarantee but barriers help), but this is a bit new to me so I am trying to work out the best way to go:
  • Prevent someone from reading the code from the STM32
  • Prevent someone from taking a DFU code update and applying it to a copied PCB
My plan is to do the following, so I am looking for feedback on the pros and cons of doing each of these:
  • To prevent someone from reading the code I will use an ST-LINK/V2 to set the required bits before shipping as ST DfuSe does not seem to give this option
  • To prevent the use of a DFU update sent to (or downloaded by) a customer being used in a copied board I plan to use a secret key (if it is secure enough to keep it inside the code) and to hash it (SHA256 in the uhashlib) with the STM32 serial number (pyb.unique_id()). This will then be supplied in a "license.txt" file on the SD card which locks the STM32 to the hardware (I hope!) and on power up it checks if the license matches the internal hash with the secret key and STM32 serial number
So basically my questions are as follows:
  • It seems you cannot set the required security bits in the STM32 using DfuSe?
  • If I connect an ST-LINK/V2 to the board (Pyboard 1.1) then I assume I will be able to set the required security bits?
  • Is using a secret key stored in the firmware along with the STM32 serial number a reasonably secure method to prevent a DFU firmware update being used in a copied board?
Any comments and feedback on this would be appreciated as it seems to be an important area for those of using using Micropython in commercial products.

uhashlib – hashing algorithms
http://docs.micropython.org/en/latest/l ... t=uhashlib

pyb — functions related to the board
http://docs.micropython.org/en/latest/l ... 0unique_id

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: Protecting MicroPython source code and DFU updates

Post by jimmo » Sat Jun 08, 2019 11:42 am

Dugite wrote:
Sat Jun 08, 2019 12:54 am
Prevent someone from reading the code from the STM32
If you are distributing DFU files for updates, then that's the same as them reading the code back from the STM32. A DFU file is (with a small amount of extra config / checksums etc, pretty much exactly a binary copy of what ends up in flash).
Dugite wrote:
Sat Jun 08, 2019 12:54 am
It seems you cannot set the required security bits in the STM32 using DfuSe?
I've only ever tried to un-set the security bits (to put custom firmware on an existing device) -- but yeah, that was the conclusion I came to also.

These bits prevent flash readout via SWD, but I've never looked into this on a board with DFU though... does ST's factory DFU bootloader know to respect the security bits and not provide flash download? AN5156 seems to suggest that this is the case?
Dugite wrote:
Sat Jun 08, 2019 12:54 am
If I connect an ST-LINK/V2 to the board (Pyboard 1.1) then I assume I will be able to set the required security bits?
On a pyb1.1, the SWCLK/SWDIO pins are shared with other functions (two of the on-board LEDs). The pins are accessible on the bottom row of the board (on the double row - P4 & P5). So in order to connect the ST-Link, you'll need to first (from Python) set those two pins back to their default AF.

machine.Pin.cpu.A13.init(mode=machine.Pin.ALT, alt=0)
machine.Pin.cpu.A14.init(mode=machine.Pin.ALT, alt=0)

(Or do this while the board is in DFU mode).
Dugite wrote:
Sat Jun 08, 2019 12:54 am
Is using a secret key stored in the firmware along with the STM32 serial number a reasonably secure method to prevent a DFU firmware update being used in a copied board?
It depends how determined the person who is attempting to copy your board is. I could imagine a way someone could figure this out and generate their own license files, and I've certainly seen more complicated feats of reverse engineering. But they'd have to be fairly determined. (That said, I have personally shipped software with much less sophisticated protection in place :) ).

Another useful step to consider is disabling the REPL and any other way that allows the user to run their own code (micropython or otherwise). (Modify ports/stm32/main.c to achieve this). Similarly, disabling the USB mass storage so they can't modify main.py.

Consider also disabling things like machine.mem8, etc.
Dugite wrote:
Sat Jun 08, 2019 12:54 am
(SHA256 in the uhashlib)
Sorry I don't want to tell you how to suck eggs, but just crossing all the i's etc... whichever approach you take, make sure you salt the hash too, just to make it that little bit harder.

User avatar
Dugite
Posts: 21
Joined: Thu Jan 18, 2018 1:29 pm

Re: Protecting MicroPython source code and DFU updates

Post by Dugite » Sat Jun 08, 2019 2:57 pm

@jimmo: Thanks for the reply, much appreciate your comments.
jimmo wrote:
If you are distributing DFU files for updates, then that's the same as them reading the code back from the STM32.
True, but if you have some control over the updates (i.e. registration required) then at least no one has any code until an update is requested, if ever. So preventing reading of the STM32 memory is again just another barrier someone has to get over.

I am going to order and ST-LINK/V2 and see how it works so will post an update when I understand this part of the programming and protection.

I plan to disable REPL but I cannot disable the USB mass storage as log files and logs are written to this for the user to access and copy along with perhaps a license key file. It seems you can just build your code as modules with MicroPython and then add a file "SKIPSD" to the flash so all of your code then runs from flash memory leaving the SD card for logs, license etc.

One of the main things which perhaps provide the most security is the SHA256 hash? It would mean you need to get the STM32 serial number of every device shipped and add this to a secret password that also needs to be inside the STM32 DFU file so it can compare on first power up if it matches the one you place inside the license file on the SD card?

Any ideas on how secure this license file idea would really be or how to best implement this given the DFU file could be available to look for the secret password? (here is the security hole but there are perhaps good ways to hide it?). If you can secure this part enough then the DFU is basically useless to anyone trying to use it in copied hardware?

One option to hide the secret password could be to distribute it around the code with a few function calls and some maths? How hard would this be to find in a DFU file?

One method I have implemented to test is as follows:

1. On boot up, copy the license.txt file from the SD card to flash memory and delete it from the SD card;
2. Store a secret password in the code (hiding it to be confirmed) then on boot up perform a SHA256 hash and compare this with the hash stored in the license.txt file stored in flash memory;
3. If the hash values match run the code as normal, if not enter some fault mode.

The above method perhaps appears like a good solution to protecting your source code, but it means if you ship your product without an SD card, you will still need to have an SD socket to load the license.txt file so it can be copied to flash memory before shipping (remove SD card before shipping).

Any comments and idea on this much appreciated :)

Post Reply