Skip to main content
emobility.academy
M.TechDiagnostics & cybersecurityAdvanced About 10 weeksKit only

Secure Boot and Signed Firmware for an EV Control Unit

You build a secure bootloader for the kit's STM32F103 that verifies a digital signature on the application firmware before running it, and accepts signed updates over UART staged in SPI flash. You measure boot time, analyse the attack surface and document what the F103's protections can and cannot guarantee.

Uses: UART · SPI

The problem

If an attacker can change an EV control unit's firmware, every safety function can be bypassed. Secure boot ensures only firmware signed by the manufacturer runs, and signed updates prevent malicious reflashing, but low-cost MCUs without a hardware root of trust need careful design.

Objectives

  • Partition flash into a bootloader and an application, with a firmware header.
  • Verify SHA-256 hashes and public-key signatures (Ed25519 or ECDSA P-256) in the bootloader.
  • Implement a signed update protocol over UART with staging in SPI flash and rollback protection.
  • Use read-out and write protection options and analyse their limits.
  • Measure boot time, update time and code size.

What you need

From the EV Embedded Development Kit

  • STM32F103C8T6 microcontroller unit (Arm Cortex-M3)
  • Reset, boot-mode and programming headers
  • SPI flash memory
  • Serial UART interface
  • 16×2 LCD
  • RGB LEDs and a buzzer

Software

  • STM32CubeIDE
  • Embedded C with HAL/LL drivers
  • A small open-source signature library in C (for example Monocypher for Ed25519 or micro-ecc for ECDSA P-256)
  • Python with the cryptography package for key generation and signing
  • STM32CubeProgrammer for option bytes

Extra parts

None. Everything this project needs is on the kit.

Key concepts

Root of trust
The first code that runs and is trusted without verification. Here it is the bootloader in write-protected flash, which then checks everything else.
Digital signature
The firmware hash is signed with a private key kept off the device; the bootloader holds only the public key, so it can verify but not create signatures.
Read-out protection (RDP) and write protection
On the F103, RDP level 1 blocks debugger reads of flash and write protection locks chosen pages. The F1 series has no RDP level 2, so protection can be removed by a mass erase, which also erases the firmware.
Anti-rollback
A version number inside the signed header is compared with a stored minimum, so an attacker cannot install an older, vulnerable but validly signed firmware.

Step-by-step guide

  1. 1

    Define threats and requirements

    Write a threat model: an attacker with UART access tries to install modified firmware, an older signed version, or corrupt an update by cutting power. Out of scope: invasive chip attacks. Set requirements: only signed firmware runs, failed updates leave a working image, versions cannot be rolled back, and boot verification time is measured and reported. Keep the threat model short and refer back to it when testing each attack.

    Checkpoint: A threat model and requirements list agreed with your guide.

  2. 2

    Partition the flash

    Reserve the first pages (for example 24 KB) for the bootloader and the rest of the 64 KB for the application. Edit the application linker script to start at the new address and set SCB->VTOR to its vector table at start-up. Define a header at the start of the application: magic, version, image length, hash and signature. Use SPI flash as the staging area for new images.

    Checkpoint: The bootloader jumps to an application at the new address, and the application's interrupts work.

  3. 3

    Implement hashing and verification

    Add SHA-256 and a signature verification library to the bootloader. On the PC, generate a key pair with Python's cryptography package and keep the private key off the device. Write a signing script that builds the header and signs the image. In the bootloader, hash the application, verify the signature with the embedded public key and only then jump. Never commit the private key to the project repository; store it separately.

    Checkpoint: A signed image boots, and changing one byte of it makes the bootloader refuse to boot and show an error on the LCD.

  4. 4

    Measure verification cost

    Measure SHA-256 time over the image and signature verification time with the DWT counter. On a Cortex-M3 without an FPU or crypto hardware, public-key verification takes noticeable time, so report it and consider verifying the full image only after updates, with a faster check on normal boots, analysing the security trade-off this makes. Report the measurements for both a small and a full-size application image, since hashing time grows with image size.

    Checkpoint: A table of hash time, verify time and bootloader flash size.

  5. 5

    Build the update protocol

    Define a UART protocol with commands to start an update, send blocks with CRC and finish. The bootloader writes received data to SPI flash, verifies the signature and version of the staged image, then copies it to internal flash and verifies again. Keep the old image valid until the new one is fully verified, or keep a backup in SPI flash to restore.

    Checkpoint: An update of a signed image succeeds end to end, and an unsigned or tampered update is rejected without changing the running firmware.

  6. 6

    Add anti-rollback and power-fail safety

    Store the minimum allowed version in a dedicated flash page or in SPI flash with redundancy, and refuse images with lower versions. Test power loss at many points during an update by switching off the board, and make sure the device always boots either the old or the new verified image. Also test what happens if power fails while the minimum version itself is being updated, which must never leave the device unable to boot.

    Checkpoint: Twenty interrupted updates at different points all recover to a valid image, and a lower-version signed image is refused.

  7. 7

    Apply hardware protections

    With STM32CubeProgrammer, set write protection on the bootloader pages and enable RDP level 1. Confirm that the debugger can no longer read flash and that the bootloader pages cannot be rewritten by the application. Document that removing RDP level 1 triggers a mass erase, so an attacker loses the firmware but can still reflash the chip, and that the F103 has no secure key store.

    Checkpoint: Debugger reads blocked, bootloader pages protected, and recovery procedure documented.

  8. 8

    Test attacks

    Try each threat: unsigned image, image signed with the wrong key, modified header, replay of an old version, truncated image, and corrupted blocks. Also try writing the bootloader area from the application. Record results for each. Script as many of these as possible in Python so they can be rerun after every bootloader change. For each attack, record the bootloader's response on the LCD and over UART, and confirm that the running firmware was not changed by checking its hash afterwards.

    Checkpoint: A test table with every attack rejected.

  9. 9

    Document the design

    Write up the architecture, flash map, protocol, measurements and security analysis, including residual risks such as glitch attacks and the lack of RDP level 2. Explain how production ECUs use hardware security modules or secure elements to close these gaps. Include the flash map, the header layout, the update protocol sequence and a table linking each threat to the countermeasure and test that addresses it. Add a recovery procedure for a device whose bootloader must be replaced.

    Checkpoint: A report and a demo of a rejected tampered update.

Testing & validation

  • Tampered, wrongly signed and rolled-back images are rejected.
  • Interrupted updates always recover to a valid image.
  • Read-out and write protection confirmed with a debugger.
  • Boot and update times measured.

Expected results

A working secure bootloader and signed update path on the STM32F103 with measured costs, tested attack resistance and a clear statement of the protection limits of this class of MCU.

Research angle for your M.Tech thesis

Research questions: what level of firmware integrity can be achieved on a low-cost MCU without a hardware root of trust, and at what cost in boot time and flash? Which design choices (full versus deferred verification, A/B images versus staging) best balance safety, availability and security? Metrics: boot time, update time, bootloader size, recovery success rate under power loss, attack test coverage. Baselines: unprotected boot, CRC-only boot. A good thesis is a careful engineering study with tested claims and honest residual-risk analysis.

Take it further

  • Add encrypted firmware images so the code is confidential in transit.
  • Deliver updates over CAN using UDS download services.
  • Add an external secure element over I2C for key storage.
  • Compare Ed25519 and ECDSA P-256 verification cost.

Viva and review questions

Why keep only the public key on the device?

The public key can verify but not create signatures, so even if an attacker reads it, they cannot sign their own firmware.

What does RDP level 1 protect against on the F103?

It stops debugger and boot-loader reads of flash. Removing it forces a mass erase, so the firmware is lost rather than read out, but the chip can then be reprogrammed.

How do you prevent a downgrade attack?

The signed header contains a version number and the bootloader stores a minimum allowed version, refusing anything older even if it is validly signed.

Related EV projects

All 100 EV projects