Secure boot SGK/SRK best practices

I’m in the process of trying to understand and explore the key management side of secure boot on an IMX8MP in order to start considering a roadmap and technical plans for our implementation.

As it is I understand this is much like a standard PKI tree where there is a root certificate, four subordinate root keys (SRK) and an initial set of four image signing keys (SGKs), and that the iMX8 has a limit of four SRK hashes which can be stored in the OTP area, giving you up to three possible keys that can be revoked in case of compromise or other security reasons.

The documentation seems to suggest it is possible to generate additional SGKs and SRKs in your PKI tree, and I am trying to understand the exact use case here. It seems that generating additional SRKs (beyond 4) isn’t typically useful since those must have their hashes fused in the SoC to be valid. Is the intent here that if one key is compromised you might generate a 5th SRK and start fusing new devices with SRKs 2 thru 5 and omitting the compromised SRK1?
Additional SGKs are also intriguing in terms of PKI “best practices”, but really not elaborated on what or how they are intended to be used.

I’m looking for additional information on the following points that aren’t very clear to me right now:

  • What’s the minimal set of items required to sign during the build? I would guess either only the desired SGK (or SRK?). The most secure approach would be to avoid storing all 4 SRKs and SGKs in the same location and only expose the single one currently in use, but the documentation seems to imply you maintain your entire key PKI tree alongside the build environment somewhere which means if one key is compromised, they probably all are.
  • If only the SGK is required during signing, it is possible (and advisable) to generate one SGK for each build agent, such that should one SGK be compromised, that particular SGK can be invalidated via PKI and replaced without needing to discard the entire SRK?
    • It looks like the layer configuration asks for the SRK index, but my current understanding here is that this is necessary to instruct the AHAB which key index to check against, not necessarily that this SRK must be present during signing
  • The CST asks for certificate validity period. A response from NXP linked elsewhere here indicates this is not a concern as the CST will still sign and make bootable images even after certificate expiry and that AHAB does not verify the expiry either. But is there any real reason not to just specify an expiry significantly beyond the anticipated product lifespan (e.g. 30 years)?

Tangentially related to secure boot/signing:

  • Closing the device enables a hardened u-boot which restricts access to certain commands. I am guessing that this means custom u-boot scripts that expect those commands would no longer function. Or is it possible to have a concept of a “signed” u-boot script which may retain access to those restricted commands while disallowing them from the console or other unauthenticated sources?

Thanks for the input!
~BW908

Hi, I’m the Toradex AI Assistant.

I might make mistakes or occasionally get you wrong. Our support team will step in if needed.


Key Management on NXP iMX8MP for Secure Boot

Your understanding of the PKI structure is correct - the iMX8MP uses AHAB (Advanced High Assurance Boot) with a hierarchical key structure(1). Let me address your specific questions based on the Toradex implementation:

Key Management Best Practices

For key management on NXP iMX SoMs, you must store the PKI Tree, SRK Tables, and Efuse Hash in a safe and secure place(1). The documentation emphasizes that losing private keys means you won’t be able to sign software with corresponding keys and certificates that match the hashes used for verification on closed SoMs(1).

The NXP iMX SoMs allow you to burn 4 Efuse hashes on the SoC HAB/AHAB, giving you effectively four valid signing keys to boot from(1). You can revoke them one by one if needed, and still seamlessly boot from the other valid ones(1). The recommendation is to keep those keys in separate safe places so that if one key gets compromised, you can use the others as backups(1).

Minimal Signing Requirements

The Toradex secure boot implementation uses specific classes for different coverage levels(1):

  • tdx-signed class provides BCoT (Basic Chain of Trust) coverage
  • torizon-signed class provides ECoT (Extended Chain of Trust) coverage and includes tdx-signed

For NXP iMX SoMs, you need to configure HAB/AHAB support as described in the meta-toradex-security documentation(1). The setup requires:

  1. Download and configure the NXP CST tool
  2. Generate keys, certificates, SRK tables and Efuse Hash following NXP documentation
  3. Configure variables to match your key generation choices

SGK Usage and Multiple Keys

Regarding additional SGKs beyond the initial set, the documentation indicates this provides flexibility for key rotation and compromise scenarios. However, the specific implementation details for managing multiple SGKs in production environments aren’t fully detailed in the available sources.

Certificate Validity Periods

The sources don’t specifically address certificate validity period considerations for the Toradex implementation. This would require consulting the NXP CST documentation directly.

U-Boot Hardening and Command Restrictions

When secure boot is enabled, Toradex implements several hardening features(2):

Command Whitelisting

The system allows or denies command execution based on the device state(2):

  • When the device is open, most commands are allowed
  • When closed, only a small set of commands are permitted (those required for booting plus a few considered useful and safe)

CLI Access Prevention

Access to the U-Boot CLI is disabled when the device is in closed state(2). The behavior is:

  • If hardening is disabled, no CLI access protection takes place
  • CLI access is enabled when device is open, disabled by default when closed
  • You can keep CLI access enabled after device closure by adding the property /chosen/toradex,secure-boot/enable-cli-when-closed to the control DTB

Configuration Example

The hardening configuration is stored in U-Boot’s control device-tree blob(2):

/ {
    chosen {
        toradex,secure-boot {   /* if not present: disable Toradex hardening */
            disabled;                 /* optional: disable Toradex hardening */
            bootloader-commands {
                allow-open = <CMD_CAT_ALL>;
                allow-closed = <CMD_CAT_ALL_SAFE>;
                deny-open = <CMD_CAT_ALL_UNSAFE>;    /* optional, discouraged */
                deny-closed = <CMD_CAT_ALL_UNSAFE>;  /* optional, discouraged */
                needed = <CMD_CAT_NEEDED>;           /* optional, discouraged */
            };
        };
    };
};

(2)

For more detailed key management strategies and production deployment considerations, I recommend reviewing the complete documentation in the meta-toradex-security layer and consulting with your security team about the specific key rotation and management policies that best fit your use case.

Best regards, Toradex AI Assistant.


Did you like my answer? :+1: :-1:

If I answered your question, please tick the “Solution” checkbox.

For follow-up questions to me, please use @ToradexAI in your post.

Greetings @bw908,

What’s the minimal set of items required to sign during the build?

In theory for the signing itself you select one of the SRKs to be used for the actual signing. However, as far as I know and understand HAB, you generate up to 4 during the key/cert generation. Then, everything that got generated gets set in the fuses.

I don’t think it’s possible to say generate only 2, fuse those, then later generate the other 2 and fuse those. Since fuses are one time programmable. At least I don’t see anything in the NXP documentation that would suggest this is possible.

If only the SGK is required during signing, it is possible (and advisable) to generate one SGK for each build agent, such that should one SGK be compromised, that particular SGK can be invalidated via PKI and replaced without needing to discard the entire SRK?

In theory you could only generate one SRK in a build and use that. But as I said before if you fuse the information of 1 SRK to a device, I don’t think you can then go back and fuse more. Which makes this kind of moot. As if this one and only key were to become compromised then you can’t fuse more keys to a device to “fix” it.

But is there any real reason not to just specify an expiry significantly beyond the anticipated product lifespan (e.g. 30 years)?

As far as I know, no. I also saw on the NXP forums that this “expiry” period doesn’t seem to actually serve a functioning purpose.

Or is it possible to have a concept of a “signed” u-boot script which may retain access to those restricted commands while disallowing them from the console or other unauthenticated sources?

The way our hardening works, is that it disallows execution of “insecure” commands. No matter what is executing the commands. Since in theory any source capable of executing U-Boot commands could be compromised. You can of course override this behavior to allow execution of certain commands even when the device is closed, but that would be at your own understanding and risk: meta-toradex-security/docs/README-secure-boot.md at scarthgap-7.x.y · toradex/meta-toradex-security · GitHub

Best Regards,
Jeremias

Thanks for the reply.

To clarify, I am saying we would generate all 4 SRKs at once , fuse their hashes together, and then do [something] to appropriately securely all but the minimum required files for producing a signed build. The reasoning here being that if (say) a build agent is compromised and its signing keys are stolen then only the key it has access to is a problem. If all 4 keys must exist on the agent at any given time to produce a signed artifact for one key, then that becomes a point of failure where one compromised key means all 4 are probably compromised. The documentation really doesn’t cover any of this and so I’m looking to understand “Of a fully generated PKI tree for AHAB, what is the minimum that must be exposed in order to sign a build with one particular given key” while the remaining files are placed in appropriate offline and duplicated storage.

Additionally, reading the documentation it sounds like the SRKs are the items that are fused into the SoC, but a subordinate key called the SGK is actually used to do the signing during the build - hence my other questions regarding capabilities of rotating and assigning these SGKs independently of the SRKs as an additional layer of protection.

Appreciate the clarification on the scripts; we’ll have to think about that a bit more and how we approach it; currently we use u-boot’s environment as a minimal graphic charging display for our device; this is currently implemented as a script to be loaded from storage so that it is easily updated and debugged. Sounds like it would be better from a security standpoint to move that into a custom u-boot command instead once we start securing devices.

I see, I think I understand what you’re saying. So you will generate 4 SRKs and fuse all the information as is usual. But, on the actual machine doing the secure-boot build you only want the key/cert files needed for the process.

That should be possible if that’s what you want. The signing script in meta-toradex-security: meta-toradex-security/recipes-bsp/u-boot/files/imx8m_sign.sh at scarthgap-7.x.y · toradex/meta-toradex-security · GitHub

Refers to specific cert/key files. That is to say it only needs SRK1_* and the corresponding files it doesn’t need the other files to do the signing. How these specific file-related variables get set is done here: meta-toradex-security/classes/imx-hab.bbclass at scarthgap-7.x.y · toradex/meta-toradex-security · GitHub

Which in short, it only needs to know the directory path to where the key/cert files are, and the chosen index (set via TDX_IMX_HAB_CST_SRK_INDEX). So if you set the index to say “3”, then you really only need SRK3_* and the other corresponding files to be present during the build.

Best Regards,
Jeremias

Thanks.

I also found this document which seems to provide a use case for the subordinate SGK keys:

https://community.nxp.com/t5/i-MX-Processors-Knowledge-Base/i-MX8X-security-overview-and-AHAB-deep-dive/ta-p/1803083

Of course this is in the context of a separate OEM, but flow appears similar to what I am interested in - in that further subordinate keys can be used to sign (one layer removed from the SRK) which offers better protection against SRK compromise.

But based on your description above it sounds like the Toradex implementation does not perform any operations the SGK keys.

Thanks!

Wait I think there might be a misunderstanding. SGKs are in the Advanced High Assurance Boot (AHAB), workflow. The HAB workflow does not use these I believe and only has SRKs. You mentioned you’re on the i.MX8M Plus, correct?

This SoC uses HAB not AHAB. AHAB is for the i.MX8 or i.MX8X. All the information I’ve been sharing prior was for HAB not AHAB.

Best Regards,
Jeremias

Ah, thanks for the clarification, that explains some of my confusion - I think I’m all set now.

Glad I could help clarify.

Best Regards,
Jeremias

My view on SGKs, and in general NXP’s approach to using X.509 PKI in the HAB process, is that it more often causes confusion than it does anything helpful. I think that it can be helpful in cases where there is some heavy existing PKI management infrastructure in place, but even in these cases I think it can lead to blind spots if developers aren’t extremely careful to fully understand the security architecture.

Let me first point out a misunderstanding from your first post:

As it is I understand this is much like a standard PKI tree where there is a root certificate, four subordinate root keys (SRK) and an initial set of four image signing keys (SGKs), and that the iMX8 has a limit of four SRK hashes which can be stored in the OTP area, giving you up to three possible keys that can be revoked in case of compromise or other security reasons.

SRK stands for Super Root Key, not subordinate root key. It is not subordinate in any sense: it is only the public keys of the SRKs that are OTP programmed into the SoC–the root CA and its keys are not used at all! So even though you generate a cert for each SRK, and a root certificate authority for signing each of these certs, the certs never actually get used for verification by the device for the first boot stage. I will reference this diagram from our developer page on secure boot:

The generally accepted best practice for secure boot is this type of chained trust. The ROM code validates the signature of the bootloader based on an OTP-fused key, and the signed bootloader contains a (different) public key that is used to validate the signature of the next stage of boot, and so on.

The idea behind using a full PKI tree, with a root CA, SRKs, and SGKs is that you could achieve a similar architecture via X.509 PKI. But I believe that in 99.9% of cases, this adds complexity without yielding a security benefit–and added complexity is inherently bad for security, so it’s a net negative.

For the first stage, even with AHAB and SGKs, you still need to sign each final bootloader image with the SRK. (Note that this is necessarily true from cryptographic first principles. The first-stage, immutable boot rom can neither access a reliable source of time nor the internet, so it has no way to effectively revoke an SGK or update its trust store; that’s why you can’t rely only on the SGK and must sign the whole thing with the SRK.)

So, since you still need to use the SRK to sign your bootloader, what’s the point of having the SGK and the PKI tree for the first stage? I would argue that there is none.

So let’s consider the other case, where you use SGKs later in the boot process. In this version, you would sign your OS container using something in the HAB/AHAB hierarchy, and have your bootloader call into the SECO to verify the OS container. But once the bootloader is loaded, the SECO has no more control over the boot process. It’s just an oracle that u-boot can consult to validate the signature of the OS container. I prefer a straightforward implementation inside u-boot that employs FIT image signing and verification rather than shoehorning in an NXP-specific boot process that’s required to use the AHAB container format.

Thanks Jon,

That was helpful/informative - I agree the documentation on NXP and Toradex is fairly straightforward on “here’s what to do to get it working” but (especially on NXP’s part) contains very little substance on WHY you are inputting the options you are told to, or context for why they matter. A good example is during key creation you are asked to choose ECC vs RSA and then a key length, but no context is offered to indicate the considerations that might go into this - Certainly general cryptographic principles apply (e.g. bigger keys are harder to guess as computing power increases) but those alone don’t cover any implications that are specific to their implementation - why not just choose the biggest key size possible? Does that mean the CST tool takes longer to sign? does verification take longer?, etc.

PKI (in AHAB) absolutely makes sense in an OEM sub-vendor scenario they propose, but as you point out… it’s just added complexity in 99% of use cases and for the 8MP and HABv4 it certainly sounds like just generating a collection of 4 keys without any infrastructure to add to the confusion would have greatly simplified much of the documentation and process.