MCU usually supports a feature to disable reading out its content of flash memory for external use.
Such a feature is useful when we build a device like Gnuk Token, because we can make sure that secret data on a device cannot be read out.
Historically, this feature was implemented to protect reading out a program from an MCU, so that replication of a device cannot be done easily by an independent vendor.
In this article, we discuss how we can design such a feature from the viewpoint of our major use case (which is a bit different to the "code protection"), and consider requirements for an implementation having the feature.
Terminology
Bootloader
A program in System memory to support access to Main Flash memory and Configuration Bytes.
BOOT Pin
MCU has BOOT Pin to configure how MCU boots (along with Configuration Bytes).
Configuration Bytes
MCU has Configuration Bytes (sometimes called as Option Bytes) to select protection and boot mode.
DEBUG interface
MCU usually has hardware DEBUG interface like JTAG or SWD port. Through such an interface, MCU can be monitored its execution, can be controlled from host.
Device
A device is a hardware which uses an MCU.
"factory-reset" of device
A procedure to reset a device to an initialized state of factory of device vendor, such that all end-user data erased.
"factory-reset" of MCU
A procedure to reset MCU to an initialized state of factory of MCU vendor, such that Configuration Bytes erased (to select default boot mode of Bootloader and to select non-protected Main Flash memory), and all content of Main Flash memory erased.
Main Flash memory
Main Flash memory is flash memory which is connected to MCU core internally, where code and data reside.
Main Flash memory is either protected or non-protected. When protected, reading out the content externally must not be possible.
System memory
System memory is ROM in MCU, which has an implementation of Bootloader.
Our use case
- At a factory of MCU vendor, MCU is shipped with erased Configuration Bytes and erased Main Flash memory.
- A device vendor builds a device, using an MCU. At a factory of device vendor, the MCU is flashed by an application program to test the hardware.
- From a device vendor, an end user receives a device (optionally, along with an external representation of binary version of an application program, and its souce code).
- An end user may build the application program from its source it by himself. The build process of the external representation of binary version of an application program should be reproducible.
- An end user may download the external representation of binary version of the program from the device vendor.
- An end user should check if binary version of an application program on the device is authentic one. By a device vendor, the method to check its authenticity must be provided.
- He must enable protection to let a device boot from an application. (Or else, the MCU boots from bootloader.)
- Conditions for an MCU:
- An application program can only run
- With protection enabled, or,
- With protection disabled, using DEBUG interface
- Using DEBUG interface must be only possible with protection disabled.
- An application program can only run
- An application program may support "factory-reset" of MCU. When an end user asks "factory-reset" of MCU, all content of Main Flash memory is erased, and then, Configuration Bytes is erased.
- A method of recovery from wrong application program should be provided.
How an MCU supports Flash Memory Read-Out Protection
DEBUG mode
DEBUG mode should be only enabled in non-protected configuration.
It is good that DEBUG interface is disabled hardware-wise completely with protected configuration, on the RESET of MCU, in an implementation of MCU.
On DEBUG mode, MCU can be monitored and controlled by host. Reading-out the content of flash is possible.
Boot selection
By hardware, BOOT Pin should be available to force boot from System memory. It specifies how MCU boots on RESET:
- Boot from System memory to run Bootloader
- Boot from Main Flash memory to run a user program
Configuration Bytes
Configuration Bytes have following data.
Bit for boot selection
- Bootloader in System memory (factory default)
- Main Flash memory
Bit for Main Flash protection
- not-protected (factory default)
- protected
SHA-2 hash of Main flash (32-byte or 64-byte): Read-Only
This is only valid when protected.
When Main Flash memory is configured to protected, then, MCU internally computes SHA-2 hash and writes the hash to Configuration Bytes.
This is useful for a user to check the content of Main Flash memory without accessing Main Flash memory directly.
Bytes for User use
Initial Flashing MCU
There are two method; By Bootloader or by DEBUG interface.
Either case, the procedure is:
- Flash each page of Main Flash memory
- [Optionally] Configure protection and boot mode
Running MCU with Main Flash memory
Boot from Main Flash memory, MCU runs a user's program. In this situation,
- MCU core needs read access to Main Flash memory to run the code.
- MCU core should be possible to write/erase a page of Main Flash memory, so that a user can keep data on MCU.
- MCU core should be possible to erase Configuration Bytes, so that a user of the program can optionally ask "factory-reset" of MCU, by the program.
When MCU is running, as long as the program itself does not try to export the content, it is not possible to export externally.
Failure of flashing MCU and recovery
When a user flash the MCU by wrong code and configures as protected, MCU runs with wrong code.
To recover, a user assert BOOT Pin on RESET, so that MCU boots from System memory to run Bootloader.
Then, the procedure is:
- Erase Configuration Bytes which invokes Mass Erase of entire Main Flash memory
Then, MCU is "factory-reset" state. Continue to "Initial Flashing MCU".
Bootloader command features
Common comands
Cold_reset
Reset the entire MCU (not only MCU core) to boot
Show_ID
Show MCU core ID and/or MCU ID
Show_Version
Show version of Bootloader
Non-protected
Flash_read_page
Read a page of Main Flash memory
Flash_write_page
Write a page of Main Flash memory
Enable_protection
SHA-2 checksum is computed at this protection time to be stored in option-bytes
Protected
Show_SHA-2_hash
Show SHA-2 checksum of Main Flash memory. Note that is is computed at the protection time. Even if the content of Main Flash memory is changed after protected, it shows SHA-2 checksum of Main Flash memory computed at the protection time.
factory_reset
Disable protection and erase entire Main Flash memory (factory-reset)
Consideration on hardware which uses such an MCU
MCU evaluation board
Debug interface, RESET pin and BOOT Pin should be available to a user.
Device as a final product
BOOT Pin should be available to an end-user when the device is opened. This enbles:
- An end-user with flashed firmware can examine the hardware and check SHA-2 hash of the firmware, by booting Bootloader.
- When re-flashing wrong firmware, it is possible to recover.
RESET pin should be optionally available to an end-user (when the device is opened). When power-on-reset is enough, it is not required to be available.
Debug interface is OK not available to an end-user.