Skip to content

Secure boot and the chain of trust

Module 4 · Secure boot and Protected Update · Module overview · Course home

mTLS proves the key lives inside the chip, but if the firmware that commands the chip has been swapped, an attacker can have the chip sign on our behalf anyway (lesson 1.2). So this lesson’s question is: “is the firmware running right now the firmware we meant to run?” — and on this board, who checks that, and how far does the check go?

By the end of this lesson you will:

  1. Explain the role of the CM33_S core in the firmware template’s secure boot
  2. Draw the chain of trust from ROM to application, and mark where signatures are checked
  3. Explain the difference between secure boot and firmware encryption
  • Already covered: Lesson 3.2: MQTTs to the TESAIoT Platform, and review signatures from lesson 1.2
  • Software: the SDK’s bento-firmware-template-mtb-only template at ef72c1b, already building
  • What this lesson will not have you do: provisioning a device to enable secure boot (secure_boot=true in the OEM policy), and transferring device ownership with an OEM key. The README of Infineon’s basic secure app example says that once provisioned, Extended Boot opens the first image only if its signature verifies. This changes the device’s behaviour at the chip level, and must follow AN237849 Getting started with PSOC™ Edge security, done by someone who has already decided to do it and who can manage the OEM key.

The “which core does what” table in the template’s README has this as its first row.

Core Runs Typical work
CM33_S secure boot you will not touch this

Meanwhile proj_cm33_s/main.c, the whole file, is under fifty lines. Its header comment reads “CM33 Secure boot - TrustZone setup and jump to CM33_NS.” Inside main() there is only cybsp_init(), enabling interrupts, reading the stack pointer and reset handler from CM33_NS’s vector table, and jumping there.

Guess first: before jumping, does CM33_S verify the signature of the CM33_NS firmware? And if not, who checks what?

The PSoC™ Edge E84 has three cores, and its main Cortex-M33 is split into secure and non-secure sides with TrustZone. So the template has three projects: proj_cm33_s, proj_cm33_ns, proj_cm55. Infineon’s example README explains the order: Extended Boot opens the CM33 secure project from a fixed location in memory. CM33 secure sets up protections, then opens the CM33 non-secure app; CM33 non-secure then starts the CM55 core. In our template, this last step lives in init_cm55_boot(), which calls Cy_SysEnableCM55(), per chapter B1 of the SDK docs.

So CM33_S is the first user image that Extended Boot sees, and the only joint where Extended Boot can verify a signature at all. The template’s common.mk has a SECURE_BOOT switch with two values.

  • SECURE_BOOT=0 (the default) uses configs/boot_with_extended_boot.json. The CM33_S image gets only the MCUboot header and is not signed.
  • SECURE_BOOT=1 uses configs/secure_boot_with_extended_boot.json. The CM33_S image is signed with the OEM root-of-trust key that a device provisioned secure_boot=true requires. The build log prints confirmation of which key file CM33_S will be signed with.

Any value other than 0 or 1, such as true or yes, makes the build stop with an error immediately. The comment in the file explains why: a mistyped value must never turn into a silently unsigned build.

2. This board’s chain of trust, and where signatures are actually checked

Section titled “2. This board’s chain of trust, and where signatures are actually checked”

The root of trust is the part we trust with no one else checking it. ETSI EN 303 645 provision 5.7-1 explains that a hardware root of trust is one way to make secure boot meaningful. On this board, that starting point is Infineon’s code inside the chip, and each stage opens the next. The question is: before opening it, is there a check?

Boot ROM (Infineon's code inside the chip)
│
▼
Extended Boot (Infineon's)
│ verifies the CM33_S image's signature with the OEM key
│ ✔ when the device is provisioned secure_boot=true and built with SECURE_BOOT=1
│ ✘ in the template's default state (SECURE_BOOT=0)
▼
CM33_S (proj_cm33_s) cybsp_init(), then jumps to CM33_NS's reset handler
│ ✘ does not verify CM33_NS's signature (the template's main.c)
▼
CM33_NS (proj_cm33_ns) FreeRTOS, PSA + the OPTIGA driver, WiFi, MQTT, then Cy_SysEnableCM55()
│ ✘ does not verify CM55's signature
▼
CM55 (proj_cm55) display, Edge AI
◦ an AI model uploaded at runtime goes through the optiga_verify_staged_model() hook (lesson 1.2)

The evidence that signing covers only CM33_S is in secure_boot_with_extended_boot.json: the sign stage takes exactly one input file, proj_cm33_s.hex. proj_cm33_ns.hex only goes through the hex-relocate stage, and proj_cm55.hex goes straight into a merge stage; all three are combined into one app_combined.hex file.

A conclusion that belongs in your threat model: even with secure boot fully enabled, this template’s chain breaks right after CM33_S. Whoever can write to the flash region of CM33_NS or CM55 can run their own code, unchecked. If your work needs a complete chain, CM33_S (or a bootloader sitting there) must verify the next image before jumping to it. Infineon has an EdgeProtect Bootloader that the example README references, but this template does not use it.

There are two other places in this course where a signature is checked, but neither is a boot stage:

  • A Protected Update manifest is verified inside the chip, by the OPTIGA™ Trust M, before it writes an object (lesson 4.2)
  • The hook that verifies an AI model uploaded at runtime — in the SDK, this defaults to a weak function that answers “this device cannot verify signatures” (-10), per the 02_model_signature_hook.c example

These two answer different questions.

Secure boot Firmware encryption
Answers Does this code come from the key’s owner, unaltered? Can someone else read this code?
Property Integrity and authenticity Confidentiality
Tool A digital signature, verified with a public key the device trusts Symmetric encryption, needing a private key on the device to decrypt
Does not protect against Someone reading the code in flash, a bug in already-signed code, an attack at runtime Running different code in its place, if no signature check accompanies it

This template has no image-encryption stage in either config file, so even with secure boot enabled, anyone who can read flash can still read the code. Secrets embedded in the image (such as a compiled-in password) get no protection from secure boot at all — this is another reason for ETSI provision 5.4-3 from lesson 3.2.

One more small thing worth noticing: the signed config sets security-counter to 1, which, in MCUboot’s format, is the number used to prevent image rollback. The documentation this course could check does not confirm how Extended Boot enforces this number, so it does not yet count as a verified firmware anti-rollback mechanism. Lesson 4.2 looks at the anti-rollback mechanism that can actually be verified, inside the OPTIGA™ chip.

The header comment of secure_boot_with_extended_boot.json, lines 1–15 (TESAIoT PSE84 Dev Kit SDK, © Thai Embedded Systems Association, Apache-2.0)

// Signed variant of boot_with_extended_boot.json — selected by SECURE_BOOT=1 in common.mk.
//
// Identical to boot_with_extended_boot.json except the CM33_S sign stage additionally
// carries "signing-key" + "security-counter", which turn the MCUboot metadata into a real
// OEM signature that Extended Boot verifies once the device is provisioned secure_boot=true.
//
// Geometry (header-size / fill-value / slot-size / hex-address) is intentionally IDENTICAL to
// the unsigned config — it is this project's real flashmap. Do NOT replace it with the values
// from mtb-example-psoc-edge-basic-secure-app (slot-size 0x80000, hardcoded 0x70100000).
//
// {{OEM_SIGNING_KEY}} is supplied by common.mk via:
// MTB_COMBINE_SIGN_ARGS += -s OEM_SIGNING_KEY "$(SECURE_BOOT_KEY)"
// Override the key with: make SECURE_BOOT=1 SECURE_BOOT_KEY=/abs/path/to/key.pem
// If you invoke run-config by hand you MUST pass -s OEM_SIGNING_KEY <path>; an unset
// variable is a hard error ("Unknown variable: OEM_SIGNING_KEY"), never a silent unsigned build.

Reading this gives you three things:

  1. Only two fields differ from the unsigned version — "signing-key" and "security-counter" in CM33_S’s sign stage. The MCUboot header is already present in both.
  2. The signature only means something once the device has been provisioned. A board not yet provisioned secure_boot=true does not check this signature at all.
  3. The author designed it to “fail loudly.” If no key is supplied, the build must error out, not silently produce an unsigned image — the same principle as common.mk refusing any SECURE_BOOT value besides 0 and 1.

For each statement below, is it true of secure boot, firmware encryption, both, or neither?

  1. Stops a competitor who buys the board from reading flash and understanding the code ____
  2. Stops a provisioned board from booting an image signed with a different key ____
  3. Prevents a buffer overflow bug in correctly signed code ____
  4. Needs a private key present on the device to work ____
  5. Prevents CM55’s firmware from being swapped in this template, even with SECURE_BOOT=1 and provisioning done ____
Solution
  1. Firmware encryption
  2. Secure boot
  3. Neither — signed code can still have bugs; a signature only tells you who it came from
  4. Firmware encryption — needs a decryption key on the device; secure boot only needs a public key to verify with
  5. Neither — in this template, signing covers only the CM33_S image

The questions below are part of the full set in quiz.yaml, which the automated grader uses.

  1. In the template’s proj_cm33_s/main.c, what does CM33_S do before starting CM33_NS? (objective 1)

    • a) Verifies CM33_NS’s signature with the OPTIGA™ Trust M
    • b) cybsp_init(), then reads the stack pointer and reset handler from CM33_NS’s vector table and jumps there
    • c) Decrypts the CM33_NS image
    • d) Connects to WiFi
    Solution

    b. There is no signature check at this stage, which is why the template’s chain breaks right after CM33_S.

  2. You build with SECURE_BOOT=1 and flash a board that is not yet provisioned secure_boot=true. What happens? (objective 2)

    • a) The board does not boot
    • b) Extended Boot has not yet been forced to check the signature, so having a signature adds no protection yet
    • c) The OPTIGA chip locks
    • d) LcsO changes to operational
    Solution

    b. The comment in the config says Extended Boot checks this signature “once the device is provisioned secure_boot=true.”

  3. Which statement correctly describes the difference between secure boot and firmware encryption? (objective 3)

    • a) Secure boot hides the code; encryption confirms who wrote it
    • b) Secure boot confirms the code comes from the key’s owner and is unaltered; encryption stops others from reading the code
    • c) They are the same thing
    • d) Secure boot needs a private key on the device
    Solution

    b. You need both together if you want integrity and confidentiality. This template has no image-encryption stage.

Read your board’s chain from the evidence. This lesson does not provision anything, and does not flash a signed image.

  • 1. Diff the two configs from the template’s folder.
    Terminal window
    diff configs/boot_with_extended_boot.json configs/secure_boot_with_extended_boot.json
    Write down every line that differs. Besides comments, how many fields are left? Does it match item 1 in the worked example?
  • 2. Prove the build system fails loudly. Build with an invalid value and record the error message.
    Terminal window
    make build SECURE_BOOT=yes
    Write one sentence on why this command failing is a good thing.
  • 3. Count what actually gets signed. Open configs/secure_boot_with_extended_boot.json, find every "command", and write a table of which stages each core’s hex file goes through (sign, hex-relocate, merge).
  • 4. Draw your own chain, in two versions: the board you are holding right now, and a shipped product with secure boot fully enabled. Mark ✔ or ✘ at every joint, each with one line of evidence (file and line).
  • 5. Update the threat model from lesson 1.1, in the T row about firmware and in the ETSI 5.7-1 row, to reflect what you found, including the fact that the chain breaks after CM33_S.
  • 6. Read further (no need to do it) in the README of Infineon’s basic secure app example. Write down the list of steps that must happen on a device before Extended Boot starts checking signatures, and mark which step you think needs someone’s sign-off before it happens.

Secure boot answers the question about firmware at power-on, but some data inside the chip — a device’s certificate, for instance — must be changeable over the device’s lifetime. The next lesson looks at how the OPTIGA™ Trust M accepts that change without trusting the host, and how it prevents rollback.

Next lesson: Lesson 4.2: Protected Update

  • In your own product, where does the chain of trust break, and who can write to the part that goes unchecked?
  • If the OEM key used for signing were to leak, how would you find out, and what would you do next?
  • Does your customer need the confidentiality of the code, the integrity of the code, or both?

Review questions

Answer on your own first, then open the answer.

  1. In the template's proj_cm33_s/main.c, what does CM33_S do before starting CM33_NS? (Objective 1)

    1. ตรวจลายเซ็นของ CM33_NS ด้วย OPTIGA™ Trust M
    2. cybsp_init() แล้วอ่าน stack pointer และ reset handler จากตาราง vector ของ CM33_NS แล้วกระโดดไป
    3. ถอดรหัส image ของ CM33_NS
    4. เชื่อมต่อ WiFi
    Show answer

    Answer: B. cybsp_init() แล้วอ่าน stack pointer และ reset handler จากตาราง vector ของ CM33_NS แล้วกระโดดไป

    ไม่มีการตรวจลายเซ็นในขั้นนี้ ห่วงโซ่ความเชื่อใจในแม่แบบจึงขาดหลัง CM33_S

  2. What does the template's build do with SECURE_BOOT=true, and why? (Objective 1)

    1. ถือว่าเป็น 1 แล้วลงนามให้
    2. ถือว่าเป็น 0 แล้ว build แบบไม่ลงนาม
    3. หยุดด้วย error เพราะค่าที่พิมพ์ผิดต้องไม่กลายเป็น build ที่ไม่ได้ลงนามแบบเงียบ ๆ
    4. ข้ามขั้น sign ทั้งหมด
    Show answer

    Answer: C. หยุดด้วย error เพราะค่าที่พิมพ์ผิดต้องไม่กลายเป็น build ที่ไม่ได้ลงนามแบบเงียบ ๆ

    common.mk ยอมรับแค่ 0 กับ 1 ค่าอื่นเป็น hard error ตามคอมเมนต์ในไฟล์

  3. With SECURE_BOOT=1 on a device provisioned secure_boot=true, at which boot link is a signature checked? (Objective 2)

    1. Extended Boot ตรวจ image ของ CM33_S เท่านั้น
    2. ทุกข้อต่อจนถึง CM55
    3. CM33_S ตรวจ CM33_NS
    4. CM33_NS ตรวจ CM55
    Show answer

    Answer: A. Extended Boot ตรวจ image ของ CM33_S เท่านั้น

    ในไฟล์ secure_boot_with_extended_boot.json ขั้น sign มีอินพุตเดียวคือ proj_cm33_s.hex ส่วน CM33_NS และ CM55 ไม่ได้ถูกลงนาม

  4. You build with SECURE_BOOT=1 and flash a board not yet provisioned secure_boot=true. What happens? (Objective 2)

    1. บอร์ดไม่บูต
    2. Extended Boot ยังไม่บังคับตรวจลายเซ็น การมีลายเซ็นจึงยังไม่ได้เพิ่มการป้องกัน
    3. ชิป OPTIGA ถูกล็อก
    4. LcsO เปลี่ยนเป็น operational
    Show answer

    Answer: B. Extended Boot ยังไม่บังคับตรวจลายเซ็น การมีลายเซ็นจึงยังไม่ได้เพิ่มการป้องกัน

    คอมเมนต์ใน config บอกว่า Extended Boot ตรวจลายเซ็นนี้เมื่ออุปกรณ์ provision secure_boot=true แล้วเท่านั้น

  5. Which statement correctly contrasts secure boot and firmware encryption? (Objective 3)

    1. secure boot ซ่อนโค้ด การเข้ารหัสยืนยันว่าใครเขียน
    2. secure boot ยืนยันว่าโค้ดมาจากเจ้าของกุญแจและไม่ถูกแก้ การเข้ารหัสทำให้คนอื่นอ่านโค้ดไม่ได้
    3. ทั้งสองอย่างเหมือนกัน
    4. secure boot ต้องใช้กุญแจลับบนอุปกรณ์
    Show answer

    Answer: B. secure boot ยืนยันว่าโค้ดมาจากเจ้าของกุญแจและไม่ถูกแก้ การเข้ารหัสทำให้คนอื่นอ่านโค้ดไม่ได้

    ต้องใช้คู่กันถ้าต้องการทั้งความถูกต้องและความลับ แม่แบบนี้ไม่มีขั้นเข้ารหัส image

Cite this lesson

If you teach from this lesson or reuse it in slides or documents, credit it with the text below. If you changed it, add (adapted) after the title.

"Secure boot and the chain of trust" from TESA Open Knowledge by the Thai Embedded Systems Association (TESA), https://github.com/tesaiot/tesa-qualification-program, licensed under CC BY-NC 4.0

Thai attribution: "Secure boot และ chain of trust" จาก TESA Open Knowledge โดยสมาคมสมองกลฝังตัวไทย (Thai Embedded Systems Association: TESA) https://github.com/tesaiot/tesa-qualification-program สัญญาอนุญาต CC BY-NC 4.0

Lesson link: https://tesaiot.github.io/tesa-qualification-program/en/courses/secure-iot-optiga/m04-secure-boot-and-update/l01-secure-boot/

This lesson adapts the source below; keep its credit too.
https://github.com/tesaiot/tesaiot-pse84-devkit-sdk/tree/ef72c1b658178eee8c38b1e47d28b006f80a59b5 · SDK security examples and docs are linked at this commit; lesson pages quote short excerpts with attribution and copy no files.

Full guide: how to cite TESA

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0

Content is licensed CC BY-NC 4.0. Reuse it non-commercially and credit the Thai Embedded Systems Association (TESA) every time. · How to cite TESA