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

Reply via email to