Skip to content

Why Secure Boot Makes Disk Encryption Provisioning Harder Than It Looks

Secure boot and disk encryption sound like two independent security features. In a real embedded product, however, their interaction can turn final factory provisioning into a delicate sequence of irreversible operations. Perform the right steps in the wrong order and a device that worked perfectly during production may no longer boot or decrypt its data after restart.

The management takeaway

Secure boot ensures that a device runs only authorised software. Disk encryption ensures that data copied from the device cannot simply be read elsewhere. Application secrets can additionally be protected by a separate secure-element chip or by a trusted execution environment: an isolated security area inside the main processor.

Each mechanism is understandable on its own. The difficulty appears when the disk-encryption key is itself protected by hardware whose behaviour depends on whether the device has already been permanently locked into its secure-boot state.

This creates a one-way transition:

  1. The device begins in an open manufacturing state.
  2. Factory software prepares and tests the hardware.
  3. Secure boot is permanently enabled.
  4. The device reboots into its final security state.
  5. Encryption keys are created or imported and bound to that state.
  6. Production software replaces the factory software.

A failure between these steps can leave a device unable to continue provisioning. A power interruption at the wrong moment can have the same result.

This is why “enable secure boot and add disk encryption” is not merely a checklist item. It is a manufacturing workflow, a recovery design and a security architecture that must be developed together.

What happened in our i.MX 8M products

We recently implemented secure boot, encrypted storage and protected application secrets for two customer products: one based on the NXP i.MX 8M Plus and another based on the i.MX 8M Mini.

One important lesson concerned the end-of-line firmware.

Here, end of line means the final manufacturing station, not the end of the product’s lifetime. The end-of-line firmware performs the last device-specific operations before a unit leaves production. These can include:

  • hardware tests;
  • assignment of device identities;
  • installation of certificates and secrets;
  • activation of secure boot;
  • creation of encrypted storage;
  • installation of the final production firmware.

Our initial instinct was to treat this firmware like any other system image and let it use encrypted storage. That creates a circular dependency.

The encryption key is protected using device-specific hardware. But the result of that protection is tied to the device’s security state. A key prepared while the device is still open must not be assumed to work after secure boot has permanently changed that state.

The provisioning firmware therefore cannot depend on encrypted storage that requires the final key before the device has entered its final state.

Why the provisioning root filesystem stays unencrypted

An embedded Linux system normally has several storage areas rather than one monolithic encrypted disk.

The bootloader and some boot files must remain accessible before Linux is running. The operating system may have a read-only root filesystem, while changing application data is kept in a separate encrypted partition.

For the manufacturing transition, our provisioning root filesystem remains unencrypted. Before secure boot is enabled, the provisioning system can mount a temporary or empty data area that does not depend on the final encryption key.

The sequence then looks roughly like this:

  1. Boot the temporary provisioning firmware.
  2. Test the device and prepare its manufacturing data.
  3. Verify that the signed firmware and recovery path are correct.
  4. Permanently enable secure boot.
  5. Reboot and confirm that the device starts in its final security state.
  6. Obtain or generate the disk-encryption key.
  7. Immediately convert that key into a device-bound protected form.
  8. Create and test the encrypted data partition.
  9. Install the production root filesystem.
  10. Remove every development path that accepts an unprotected key.
  11. Reboot again and verify the complete production system.

The reboot after enabling secure boot is not just ceremonial. It proves that the device can actually operate after the irreversible transition.

Only then should key material be bound to the final hardware state.

What is a “black key”?

NXP’s i.MX 8M processors contain a hardware cryptographic subsystem called the Cryptographic Acceleration and Assurance Module, usually abbreviated to CAAM.

CAAM can perform encryption without exposing the processor’s deepest device-specific secrets to Linux. One of these secrets is derived from one-time-programmable information inside the chip. It is unique to the device and cannot simply be read by normal software.

A normal plaintext cryptographic key is sometimes called a red key in this terminology. If Linux can read that key as ordinary bytes, an attacker who compromises the operating system may be able to copy it.

A black key is protected so that it can be used through the cryptographic hardware without being available to ordinary software in plaintext form.

For persistent storage, NXP’s terminology also distinguishes black keys from encrypted key blobs. In practice, engineering conversations sometimes use “black key” more broadly for the device-bound protected object that can safely be stored outside the secure hardware.

The important property is this:

The bytes stored on the device are not sufficient to recover the original key on another device.

The protected key material can therefore be stored on an unencrypted boot partition. Stealing the storage chip does not provide the device-specific hardware secret required to recover or use the key.

“Safe to store” does not mean that integrity no longer matters. An attacker may still be able to delete, replace or roll back the protected object. That can cause denial of service or restore an older system state. Secure designs must therefore consider integrity, versioning and rollback protection as well as confidentiality.

The kernel never receives the hardware master key

Linux interacts with CAAM through a kernel driver and the interfaces built on top of it.

The application or early boot environment can ask the kernel to perform a key-protection operation. The driver then submits that request to CAAM. The hardware uses its internal device-specific material and returns a protected result.

At no point does the Linux kernel need to read the underlying one-time-programmable master secret.

This separation is essential. If the operating system could extract the hardware root key, an attacker with kernel-level access could clone the protection mechanism onto another machine.

Instead, Linux receives access to an operation:

  • protect this key;
  • recover or use this protected key;
  • perform this cryptographic operation.

It does not receive the secret from which the protection is derived.

Are secure boot and disk encryption independent?

At the level of security goals, they are different mechanisms.

Secure boot answers:

Is this software authorised to run on the device?

Disk encryption answers:

Can someone read the stored data without the encryption key?

They can be implemented independently. A system may have secure boot without encrypted storage, or encrypted storage without secure boot.

In a production system, however, they should not be treated as completely orthogonal.

Without secure boot, an attacker may replace the early boot environment with modified software that attempts to capture the disk key when the legitimate system unlocks its storage.

Conversely, when the hardware protection of the disk key depends on the device’s secure-boot or lifecycle state, enabling secure boot changes the conditions under which the protected key is created and later recovered.

The mechanisms are therefore conceptually separate but operationally intertwined.

That interaction is what makes the final manufacturing sequence difficult.

What is generic Linux and what is i.MX-specific?

Much of the storage architecture can use standard Linux components.

Linux provides generic mechanisms for:

  • block-device encryption;
  • encrypted volume management;
  • early boot through an initial RAM filesystem;
  • mounting the real root filesystem;
  • updating system images;
  • passing keys to storage drivers;
  • separating read-only software from writable application data.

On many systems, encrypted volumes are implemented using the Linux device-mapper encryption layer, commonly known as dm-crypt, often together with the Linux Unified Key Setup format, or LUKS.

These parts are portable across many processor families.

The device-bound protection of the encryption key is platform-specific. On the i.MX 8M family, it is implemented through CAAM, its kernel driver and the hardware security configuration of the processor.

Our higher-level provisioning logic can therefore remain similar across the i.MX 8M Plus and i.MX 8M Mini:

  • obtain a plaintext key only inside a controlled provisioning path;
  • immediately ask the hardware to protect it;
  • store only the protected result;
  • refuse plaintext keys in production;
  • use the protected key during early boot to unlock storage.

The compiled kernels, device trees, drivers and board-support packages remain target-specific. The kernel abstracts many processor differences from our provisioning software, but this does not remove the need to test every supported hardware target independently.

A shared interface reduces implementation complexity. It does not make two processors identical.

Development and production must accept different inputs

During development, engineers need a practical way to create encrypted test devices.

One possible development flow is:

  1. A manufacturing or flashing tool places a plaintext test key on the device.
  2. A specially built development firmware detects it.
  3. The initial RAM filesystem asks CAAM to protect the key.
  4. The plaintext copy is deleted.
  5. The protected form is used for subsequent boots.

A production firmware must not preserve this convenience.

The production initial RAM filesystem should reject plaintext disk keys completely. Otherwise, an attacker who can influence the boot partition or update input may be able to bypass the intended device-bound provisioning process.

An updater may still receive a new key from a controlled side channel or from a suitably protected update package. But it should convert the key into its hardware-protected form immediately, without first writing the plaintext value to persistent storage.

This creates an important build-time security boundary:

  • development firmware may contain controlled provisioning facilities;
  • production firmware must remove or permanently disable them.

A configuration flag is useful, but it is not enough by itself. The production build should also be tested specifically to prove that it rejects every plaintext-key path.

The failure modes are mostly about transitions

Many embedded security failures do not come from a broken encryption algorithm. They come from an incomplete state transition.

Typical examples include:

  • protecting a key before the device reaches its final security state;
  • enabling irreversible secure-boot settings before testing the signed recovery image;
  • losing power after locking the device but before creating usable encrypted storage;
  • leaving a plaintext key in a boot partition, update package, log or diagnostic dump;
  • allowing production firmware to accept a development key format;
  • installing firmware that cannot understand keys created by the previous version;
  • rolling back to software that uses an older key-protection scheme;
  • assuming a process tested on one processor variant behaves identically on another;
  • creating a recovery image that was never tested on an already locked device.

The correct design is therefore not merely a sequence of successful commands. It is a state machine with explicit checkpoints, failure handling and recovery rules.

At each irreversible step, the system should know:

  • what state the device is currently in;
  • what evidence proves that state;
  • which operation may safely happen next;
  • what happens if power is lost immediately afterward;
  • whether the operation can be retried;
  • whether a unit in this state can still be recovered.

What a production-ready process should prove

Before deploying this flow on a manufacturing line, we want more than one successful demonstration device.

The process should prove that:

  • each unit receives the intended device-specific identity and credentials;
  • secure boot rejects unauthorised software;
  • the provisioning image still boots immediately after secure boot is enabled;
  • the plaintext disk key is never written to persistent production storage;
  • the protected key works only on the intended device;
  • encrypted storage survives normal updates;
  • recovery firmware works on a device that is already locked;
  • rollback rules are defined and tested;
  • interrupted provisioning can be detected and handled;
  • production firmware refuses all development key-injection mechanisms;
  • secrets do not appear in logs, crash reports or diagnostic exports;
  • the process works separately on every supported processor and board revision.

Power-cut testing is particularly valuable. Removing power after every meaningful provisioning step is an effective way to discover assumptions that remain invisible during a clean, uninterrupted factory run.

Security features form a system

Secure boot, disk encryption and protected application secrets are often presented as individual product features.

In reality, their value depends on the connections between them:

  • secure boot protects the software that handles the secrets;
  • hardware key protection prevents the storage key from being copied;
  • disk encryption protects data outside the trusted running system;
  • the updater must preserve those guarantees across versions;
  • manufacturing must establish them in the correct order;
  • recovery must work without reopening insecure paths.

This is why the last few steps between a working prototype and a securely provisioned production device can require disproportionate engineering effort.

The cryptographic building blocks already exist. The hard part is turning them into a repeatable process that remains secure during manufacturing, normal operation, software updates, power failures and recovery.

For teams moving an embedded Linux product from development hardware to locked production units, this transition deserves to be designed as a first-class subsystem, rather than left as a collection of final factory scripts.