This follows up my report of 2026-09-08, "[SECURITY] FIT signature enforcement fails open when the control DTB has no /signature node":
https://lore.kernel.org/u-boot/CA+pz=k+hAU5dqbO4GOLJ0fRMRdyrq=ktsnwuc0ocr3r9pot...@mail.gmail.com/ Tom asked for a fix and a test following the sending_patches process, so here they are. Everything below was measured on sandbox at commit a44f46af0aa1 ("MAINTAINERS: tee: update Jens Wiklander's email address"). The fail-open ------------- fit_image_verify_required_sigs() at boot/image-fit-sig.c:187 looks up the "/signature" node of the U-Boot control devicetree and returns success when it is absent, at boot/image-fit-sig.c:203-207: /* 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; } With no /signature node there are no keys marked 'required', so nothing downstream can fail the image. The only indication is a debug() call, compiled out of a normal build. 'iminfo' at this HEAD verifies images but not configurations, so it reaches this gate directly. Against a control devicetree with no /signature node at all, and a FIT whose configuration signature carries no 'value': ## Checking hash(es) for FIT Image at 10400100 ... Hash(es) for Image 0 (kernel): sha256+ Hash(es) for Image 1 (fdt-1): sha256+ That '+' is fit_image_verify_with_data() reporting the signature verified, on a board holding no keys whatsoever. The comment beside it in boot/image-fit.c is correct that only 'required' keys can fail an image, and that is precisely what makes a missing /signature node fatal to the security property rather than to the boot. With CONFIG_FIT_REQUIRE_CONFIG_SIGS=y the same command gives: ## Checking hash(es) for FIT Image at 10400100 ... Hash(es) for Image 0 (kernel): No signature node in control FDT: FDT_ERR_NOTFOUND error! Unable to verify required signature for '' hash node in 'kernel' image node Bad hash in FIT image! Relationship to Ludwig Nussel's series -------------------------------------- The same early return exists in the configuration path, at boot/image-fit-sig.c:686-690, and that half is already being addressed. Ludwig Nussel's "Improve FIT signature handling" series has been fixing it since April and is at v8: v7 4/8, direct link: https://lore.kernel.org/u-boot/20260618144742.v7.4.6d1d5d14140677a76a7cd7bb99a9088d8c8f480c@changeid/ v8 4/8 review thread: https://lore.kernel.org/u-boot/[email protected]/ That series introduces CONFIG_FIT_REQUIRE_CONFIG_SIGS, closes the configuration gate, and also restructures the closing check at boot/image-fit-sig.c:733 to cover the case where /signature exists but holds no required="conf" keys, where reqd_sigs stays 0 and the check cannot fire. The v7 form was applied to u-boot/next on 2026-06-30 and then dropped after CI failed. This series is complementary, not competing. v2 through v8 change only fit_config_verify_required_keys(); fit_image_verify_required_sigs() is untouched throughout. That image gate is what these patches close. The Kconfig symbol here is deliberately Ludwig's FIT_REQUIRE_CONFIG_SIGS rather than a new name, so that whichever lands first the other reduces to a smaller change rather than a conflicting one. If 4/8 lands first, all that remains of patch 1/2 is the image-gate hunk. Kconfig name and default ------------------------ CONFIG_FIT_REQUIRE_CONFIG_SIGS, depends on FIT_SIGNATURE, default n, plus SPL_FIT_REQUIRE_CONFIG_SIGS which selects it. Default n is a measured choice, not caution. Full test_vboot suite on sandbox with these patches applied: option at its default (not set): 32 passed, 0 failed CONFIG_FIT_REQUIRE_CONFIG_SIGS=y: 19 passed, 13 failed The 13 are not a defect in the patch. test_vboot's first step is test/py/tests/test_vboot.py:312 run_bootm(sha_algo, 'unsigned images', ' - OK' if algo_arg else 'dev-', True) which boots an unsigned-images FIT against a devicetree that has no keys yet and asserts that it boots. That assertion encodes the old contract, so enforcing correctly breaks it: E assert 'dev-' in "... No signature node in control FDT: FDT_ERR_NOTFOUND Bad Data Hash ... ERROR -2: ... can't get kernel image!" This is the same class of CI breakage that got v7 dropped from next. Making the option default y would require test_vboot to be restructured first, which is what Ludwig's 5/8 does. Until that lands, default n keeps the shipped configuration byte-for-byte unchanged in behaviour. The console message is conditional ---------------------------------- The message is printed only when the option is enabled; the debug() call is kept otherwise. Jonas Karlman objected to making it unconditional: https://lore.kernel.org/u-boot/[email protected]/ "Yes, printing a verbose error message for something that should not always be treated as an error is an issue." Rockchip enables FIT_SIGNATURE for image hash integrity alone and has no /signature node by design, so an unconditional message is noise on every boot there. Gating it means a board that has not asked for enforcement sees no change at all. Measured with the option off: the string "No signature node in control FDT" appears 0 times in the boot output, and 'iminfo' prints the same 'sha256+' lines as an unpatched build. printf() is used rather than log_err() so that this applies to main standalone; log_err() in this file requires Ludwig's 3/8. If these are ever squashed together, log_err() is the better choice. NOT TESTED ---------- Being explicit, because some of this matters for review: - SPL: SPL_FIT_REQUIRE_CONFIG_SIGS is added and compiles through CONFIG_IS_ENABLED, but I have not built or run any SPL configuration. Compile coverage only. It needs someone with SPL verified boot. - Host tools: mkimage and fit_check_sign build with the patch, but I have not exercised any fit_check_sign behaviour change. CONFIG_IS_ENABLED is false in the host build since tools/Makefile only defines CONFIG_FIT_SIGNATURE, so host behaviour should be unchanged -- argued, not measured. - Sandbox only. I have no signed-boot hardware. Everything above is sandbox_defconfig on x86-64. - Jonas's Rockchip setup: not reproduced. I reasoned that the off path stays quiet and then measured that it does on sandbox, which is not the same as booting an RK3588. No Fixes: tag ------------- The early return is original behaviour rather than a regression. The oldest commit touching it in this path is commit b983cc2da0ba ("lib: rsa: decouple rsa from FIT image verification"), and that one moves the code from common/image-sig.c to common/image-fit-sig.c rather than introducing it. I could not identify an introducing commit with enough confidence to tag one, so I have not. Eva Crystal (2): image-fit-sig: also require signatures on the image gate test: vboot: add coverage for a control FDT with no /signature node boot/Kconfig | 27 +++++++++++ boot/image-fit-sig.c | 15 ++++++ test/py/tests/test_vboot.py | 96 +++++++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+) -- 2.53.0
