Flash Memory Read-Out Protection

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

  1. At a factory of MCU vendor, MCU is shipped with erased Configuration Bytes and erased Main Flash memory.
  2. 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.
  3. 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).
  4. 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.
  5. An end user may download the external representation of binary version of the program from the device vendor.
  6. 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.
  7. He must enable protection to let a device boot from an application. (Or else, the MCU boots from bootloader.)
  8. 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.
  9. 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.
  10. 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:

  1. Flash each page of Main Flash memory
  2. [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:

  1. 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.