Hi,
Reporting a fail-open condition in FIT signature enforcement. I am
sending this to the list per doc/develop/security.rst. I am not
claiming a remote exploit here; the issue is that the verification
gate silently reports success in a state an integrator can reach by
mistake, with no runtime indication. Details below so you can judge
the severity yourselves.
Confirmed at commit b4ac71db (2026-09-07).
Summary
-------
Both required-signature gates return success when the U-Boot control
devicetree contains no /signature node. Verified boot is then
effectively disabled, and the only indication is a debug() message
that is compiled out in a normal build.
Affected code
-------------
boot/image-fit-sig.c, fit_image_verify_required_sigs():
/* Work out what we need to verify */
*no_sigsp = 1;
key_node = fdt_subnode_offset(key_blob, 0, FIT_SIG_NODENAME);
if (key_node < 0) {
debug("%s: No signature node found: %s\n", __func__,
fdt_strerror(key_node));
return 0;
}
boot/image-fit-sig.c, fit_config_verify_required_keys():
/* Work out what we need to verify */
key_node = fdt_subnode_offset(key_blob, 0, FIT_SIG_NODENAME);
if (key_node < 0) {
debug("%s: No signature node found: %s\n", __func__,
fdt_strerror(key_node));
return 0;
}
In the configuration path, reqd_sigs also stays at 0, so the closing
check
if (reqd_sigs && !verified)
never fires either.
Why this is not caught downstream
---------------------------------
In boot/image-fit.c, fit_image_verify_with_data() the per-signature
result is deliberately non-fatal:
/*
* Show an indication on failure, but do not return
* an error. Only keys marked 'required' can cause
* an image validation failure. See the call to
* fit_image_verify_required_sigs() above.
*/
if (ret)
puts("- ");
else
puts("+ ");
That comment is correct, and it is exactly what makes the missing node
fatal to the security property rather than to the boot: with no
/signature node there are no required keys, so nothing in the chain
can produce a failure. A FIT image with absent, malformed or invalid
signatures verifies successfully and the function returns 1.
Threat model
------------
To be straightforward about the ceiling: the control DTB is U-Boot's
own, so an attacker who can rewrite it can generally rewrite U-Boot
too, and in that case this adds nothing. The realistic exposure is
different:
- A build or integration mistake that omits the /signature node
produces a board that boots unsigned images and prints nothing
unusual. There is no boot-time signal that verified boot is off.
- Platforms that keep the control DTB in a separate flash region
with weaker write protection than the U-Boot image itself.
- Downgrade of a correctly built device to an earlier DTB that
predates signing.
In all three the failure is silent, which is the part I think is worth
changing regardless of how you rate the first point.
Suggested fix
-------------
Minimally, raise the visibility: replace the debug() calls with
printf() so a missing /signature node is announced on the console when
FIT_SIGNATURE is enabled.
Better, make it fail closed under a Kconfig option, defaulting on for
FIT_SIGNATURE builds:
if (key_node < 0) {
printf("%s: No signature node in control FDT - "
"verified boot is not enforced\n", __func__);
if (IS_ENABLED(CONFIG_FIT_SIGNATURE_STRICT))
return -ENOENT;
return 0;
}
I am happy to prepare the patch for whichever form you prefer, and to
add a test under test/py covering the missing-node case.
Disclosure and CVE
------------------
I understand from doc/develop/security.rst that the project does not
assign CVEs. I originally documented this finding in February 2026.
I am happy to follow whatever timeline you prefer for public
disclosure, and will coordinate any CVE request separately rather than
making it a precondition for the fix.
Regards,
Eva Crystal (0xiviel)
XSource Security