TL;DR: Want a secure‑boot example you can run, break, and verify (not just read)? This kit gives you a clean baseline: A/B slot boot, watchdog rollback, anti‑rollback, key lifecycle, and deterministic pass/fail demos on host + QEMU.

Bare-metal secure boot you can actually run (and break) in 10 minutes

Secure boot on Cortex‑M is not a service. It’s a single decision point immediately after reset:

  • ✅ verify the candidate firmware image (format + integrity + “auth” binding)
  • ✅ decide run or refuse to run
  • ✅ behave deterministically under failure (no “crash and hope”)

Most posts explain the idea. This one stays educational and gives you a runnable baseline you can reuse.


Get the kit

Buy on Gumroad: Secure Boot Kit

  • Format: ZIP (code + docs + demos + tests)
  • License: personal / internal use (no redistribution)
  • Support: docs + community discussion
  • Need commercial/shipping rights? See FAQ (“Licensing”) below.

Proof first: what you can see happening at boot

A real secure-boot flow should answer:

  • What exactly is verified at boot?
  • What happens if the image is modified?
  • Does the system refuse to jump to application code on failure?
  • Can I reproduce the failure path reliably?

This kit demonstrates deterministic outcomes:

  • A valid image boots normally
  • A single-byte modification causes validation failure
  • Control never jumps to the application on failure
  • Retry/rollback behavior is observable and testable (A/B + watchdog policy)

Example:

Host demo output (pass/fail + rollback + key rotation)

QEMU demo output (embedded-style artifacts + policies)


10-minute quickstart (no hardware required)

From the repository root:

make test
make boot-demo-run
make boot-demo-qemu-run

What you’ll see:

  • make test → unit + integration checks for policy behaviors
  • make boot-demo-run → interactive secure‑boot simulator on your host
  • make boot-demo-qemu-run → embedded-style build + boot path executed in QEMU

<code>make test</code> output


Secure boot fundamentals

If you’re a student: this section gives you the “why” and the mental model.
If you’re a professional: skim headings, then jump to the “Hands-on mini labs.”

1) What secure boot is (and isn’t)

Secure boot means: on reset, the device only runs firmware that passes the boot policy.
That policy typically checks:

  • integrity: firmware bytes weren’t corrupted or modified
  • authenticity: firmware came from an allowed signer (or allowed key)
  • freshness: firmware isn’t an older vulnerable version (anti‑rollback)
  • resilience: updates don’t brick the device (A/B + rollback)

Secure boot is not:

  • encryption-at-rest (that’s a different control)
  • a cloud service feature
  • “security complete” by itself (debug ports, secrets handling, and runtime hardening still matter)

2) A minimal chain of trust on Cortex‑M

Bare-metal boot is simple, which is why it’s great for learning:

Reset
Bootloader starts
Select candidate slot (A/B policy)
Validate image (header + integrity + auth + rollback policy)
  ├─ PASS → Jump to application ResetHandler
  └─ FAIL → Refuse to run (halt/safe-mode/diagnostic path)

The only thing that makes this “secure” is the explicit decision point before executing untrusted code.


3) Flash layout: where things live and why it matters

A realistic update-capable system typically has:

  • Slot A: a complete bootable image
  • Slot B: another complete bootable image (trial update target)
  • Metadata pages: durable state (which slot, retry counters, rollback floor, key IDs)
  • Crashlog page: last fault record to aid debugging

A simple layout (like this kit uses):

FLASH_BASE
  ├─ Slot A (96 KiB)
  ├─ Slot B (96 KiB)
  ├─ Boot state journal page 0
  ├─ Boot state journal page 1
  ├─ Key state journal page 0
  ├─ Key state journal page 1
  └─ Crashlog page (last erase block)
FLASH_END

Why journal pages? Power can die mid-write. Journaling (two pages + sequence) lets you recover the newest valid state.


4) Image format: you need metadata to be testable

A secure-boot image is more than “raw bytes.” You need a header so the bootloader can:

  • sanity-check invariants (magic, size bounds, alignment)
  • measure integrity (CRC or hash)
  • bind authenticity (MAC/signature)
  • enforce policy (version, key id, flags)

Typical fields:

  • magic (identifies image type)
  • version (for anti‑rollback)
  • image_size
  • image_crc (integrity)
  • key_id (which key should verify this image)
  • sig0/sig1 (auth binding)

Key idea: you’re not just verifying bytes; you’re verifying meaning (metadata + payload are bound together).


5) CRC vs hash vs MAC vs signature (what each is good for)

Many beginners see “CRC” and assume it’s security. It isn’t. Here’s the clean mental model:

Mechanism Detects random corruption Resists intentional tampering Typical use
CRC32 ✅ yes ❌ no flash corruption / transmission errors
Hash (SHA-256) ✅ yes ❌ no (no key) measurement, integrity check when stored securely
MAC (HMAC) ✅ yes ✅ yes (keyed) embedded authenticity with shared secret
Signature (ECDSA/Ed25519/RSA) ✅ yes ✅ yes (public-key) authenticity with offline signing keys

This kit uses:

  • CRC32/ISO‑HDLC for payload integrity (fast, portable, incremental)
  • a keyed signature/mixing model as a reference hook that binds metadata + payload to a 16‑byte key id

For production, many teams swap the “signature hook” for HMAC or a public-key scheme depending on threat model and key handling.


6) A/B updates + watchdog rollback (how devices avoid bricking)

A/B means: you never overwrite the only bootable image.

A common policy:

  1. Boot slot B as trial (unconfirmed)
  2. If the app reaches a “healthy” point, it marks itself confirmed
  3. If not (watchdog resets), decrement retry budget
  4. When retries exhausted → fall back to last confirmed slot (often A)

Why the watchdog is important:

  • It’s the simplest way to detect “boot didn’t reach healthy”
  • It forces an automatic rollback without user intervention

This kit lets you see the trial attempts being consumed and the fallback trigger.


7) Anti‑rollback: stopping downgrade attacks

Even if your image can’t be modified, an attacker might install an older signed image with known vulnerabilities.

Anti‑rollback is the rule:

Do not boot firmware versions below a persisted floor.

Practical designs store:

  • min_accepted_version (rollback floor) in durable metadata
  • update it only when a version is confirmed healthy

This is teachable and testable, and the kit includes a demo command that attempts to stage rollback_floor - 1 and shows it being rejected.


8) Key lifecycle: rotation and fallback windows

Real products rotate keys. Key rotation raises operational questions:

  • How do you migrate from key 1 → key 2 without bricking devices?
  • How long do you accept images signed by the previous key?
  • When do you retire the fallback key?

A simple rotation model:

  • Install a new active key id (new images use it)
  • Keep the old active key as fallback during the migration window
  • Once devices are migrated, retire fallback acceptance

This kit demonstrates rotation + retirement explicitly (not time-based), so you can learn the lifecycle clearly.


Hands-on mini labs

These are short guided sequences you can paste into a terminal for screenshots.

Lab A: Show A/B fallback with watchdog resets

Expected learning outcomes:

  • how trial attempts get counted
  • why fallback occurs after repeated watchdog resets
  • what “confirmed” vs “unconfirmed” means in practice

Host demo

make boot-demo-run
/status
/stageb
/bootwdog
/bootwdog
/bootwdog
/status
/quit

demo output:

lab-A-output

Lab B: Show anti‑rollback rejection

Expected learning outcomes:

  • what rollback floor is
  • why “signed but old” can still be rejected
make boot-demo-run
/status
/stagerollback
/quit

demo output:

lab-B-output

Lab C: Key rotation + fallback-key retirement

Expected learning outcomes:

  • key migration window vs retired key
  • why explicit operational control is valuable
make boot-demo-run
/status
/rotatekey 3
/status
/retirekey
/status
/quit

demo output:

lab-C-output

Lab D: Crash diagnostics (fault → persisted record)

Expected learning outcomes:

  • why crash logs belong in flash
  • what PC/LR/xPSR tell you about a fault
make boot-demo-run
/faultdemo
/quit

demo output:

lab-D-output

Want the same “embedded artifact” feel? Run make boot-demo-qemu-run and repeat the same commands at the qemu-boot> prompt.


The practical engineering part (how to jump to the app correctly)

A classic Cortex‑M mistake: “verification passes” but the jump to app is wrong.

A typical safe-ish jump sequence (pseudocode):

// 1) Read application vector table (first two words)
uint32_t app_msp  = *(uint32_t*)(APP_BASE + 0);
uint32_t app_reset= *(uint32_t*)(APP_BASE + 4);

// 2) Deinit / disable interrupts (platform-dependent)
__disable_irq();

// 3) Relocate vector table if your core supports VTOR (not on all M0/M0+)
SCB->VTOR = APP_BASE;

// 4) Set MSP and jump to ResetHandler
__set_MSP(app_msp);
((void (*)(void))app_reset)();

In production you also consider:

  • clearing pending interrupts
  • clock/peripheral state cleanup
  • MPU/SAU configuration
  • ensuring APP_BASE alignment and address validity

This kit keeps the boot decision point clear and wires the embedded path end‑to‑end in the QEMU demo.


Introducing the Cortex‑M Bare‑Metal Secure Boot Kit

This kit is a small, readable secure‑boot baseline you can:

  • run locally (host demo)
  • run as embedded artifacts (QEMU demo)
  • intentionally break (tamper) and observe refusal behavior
  • extend into a hardened design for your own product

It’s not a black box. It’s the missing “runnable reference” between theory and production.


What you get (deliverables)

Boot policy + system behavior

  • A/B slot selection with deterministic fallback
  • Watchdog-driven retry accounting and rollback to last confirmed slot
  • Anti‑rollback floor enforcement (reject old versions)
  • Crash-log capture + readback for post‑mortem debugging

Image format + verification hooks

  • Concrete image header: magic, version, image_size, image_crc, key_id, sig0, sig1
  • CRC32/ISO‑HDLC implementation details documented (portable, incremental)
  • A keyed signature/mixing reference that binds metadata + payload to a 16‑byte key id

Note: The “signature” in this kit is a portable keyed construction designed for learning and portability. If you need public-key signatures (ECDSA/Ed25519) or HMAC, the code is structured so you can swap the verification primitive while keeping the A/B policy, metadata journals, and demos.

Power-loss-safe state

  • Dual-page boot state journal + key state journal (sequence + CRC selection)

Runnable demos

  • Host interactive demo: exercise policies without hardware
  • QEMU demo: startup + linker + image header patching + policy on emulated Cortex‑M3

Tests + CI

  • Unit + integration tests
  • GitHub Actions CI matrix (Linux + Windows) to keep behaviors stable

Porting guidance

  • Checklist for integrating on STM32 / NXP / ESP32-class targets (flash geometry, drivers, reset reasons, etc.)

Who this kit is for

  • Students: you want a real secure‑boot baseline you can see working (and failing).
  • Hobbyists / indie builders: you need a clean boot policy baseline for prototypes.
  • Teams: you want a reference architecture you can harden, audit, and integrate.

What this kit is and is not

This kit is:

  • a Cortex‑M bare‑metal secure‑boot reference
  • readable, modifiable, and designed for learning + prototyping
  • a policy-driven baseline (A/B, rollback, key lifecycle) with runnable demos

This kit is not:

  • a turnkey certified secure‑boot product
  • a full PKI, signing server, or vendor ROM replacement
  • a “ship tomorrow” security guarantee without review and adaptation

Think of it as a production-oriented baseline you can validate quickly and then harden.


If you want to harden this for production (recommended next steps)

Depending on your threat model, consider:

  1. Replace the signature hook with:
    • HMAC (shared secret) or
    • ECDSA/Ed25519 (public key in device, private key offline)
  2. Protect key storage:
    • vendor OTP/option bytes, TrustZone-M, secure element, or at least readout protection
  3. Lock debug appropriately (SWD/JTAG)
  4. Decide your update channel threat model:
    • signed update packages, secure transport, server authentication
  5. Add version monotonicity that survives flash tampering:
    • monotonic counters in OTP where available
  6. Threat model the “installer”:
    • who is allowed to write slots? how do you authenticate updates?

FAQ

Do I need a dev board?

No. You can run the host demo and the QEMU demo locally.

Is this “real” secure boot or just a demo?

It’s a real boot policy baseline with deterministic behavior and runnable demos.
For a shipping product you still need to adapt it to your threat model, choose a cryptographic primitive appropriate for your requirements, and perform review/testing.

Does it use public-key signatures (ECDSA/Ed25519)?

The kit includes a portable keyed signature/mixing reference designed to keep the example runnable and easy to understand. The verification hook is intentionally structured so you can replace it with HMAC/ECDSA/Ed25519 while keeping the same boot policy and flash state model.

Can I use this in a commercial product?

The default license is personal/internal use (no redistribution).
If you want shipping/redistribution rights, add (or request) a Commercial License tier.

Suggested wording for Gumroad:

  • Commercial License: shipping compiled firmware allowed; no source redistribution
  • Enterprise License: custom terms / source escrow / support

What do I receive after purchase?

A ZIP package containing source, docs, demos (host + QEMU), tests, and CI configuration.


Get the kit

Buy on Gumroad: Secure Boot Kit

If you’ve ever wanted a secure‑boot example that goes beyond slides and actually refuses to run modified firmware, this kit gives you a clean, educational, practical starting point.