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: a FIT whose signatures are absent,
malformed or invalid verifies successfully. The only indication is a
debug() call, which is compiled out of a normal build.

fit_config_verify_required_keys() carries the same early return, and in
that path reqd_sigs also stays at 0, so the closing
"if (reqd_sigs && !verified)" check never fires either.

'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.

Add FIT_REQUIRE_CONFIG_SIGS, which turns a missing "/signature" node,
and a "/signature" node holding no required keys, into a verification
failure on both gates. 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!

The option defaults to n, and that is a measured choice. Full test_vboot
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/py/tests/test_vboot.py:312
boots an unsigned-images FIT against a key-less devicetree and asserts
that it boots, which encodes the old contract. Restructuring that is
Ludwig Nussel's 5/8. Default n keeps the shipped behaviour byte-for-byte
unchanged.

The new console message is printed only when the option is enabled.
Jonas Karlman objected to an unconditional message: Rockchip enables
FIT_SIGNATURE for image hash integrity alone and has no /signature node
by design, so an unconditional message would be noise on every boot
there. 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 stays applicable 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:

- SPL: SPL_FIT_REQUIRE_CONFIG_SIGS compiles through CONFIG_IS_ENABLED,
  but no SPL configuration was built or run. Compile coverage only.
- Host tools: mkimage and fit_check_sign build, but no fit_check_sign
  behaviour change was exercised. CONFIG_IS_ENABLED is false in the host
  build since tools/Makefile only defines CONFIG_FIT_SIGNATURE, so
  unchanged host behaviour is argued, not measured.
- Sandbox only: sandbox_defconfig on x86-64. No signed-boot hardware.
- Jonas's Rockchip setup was not reproduced.

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"),
which moves the code from common/image-sig.c to common/image-fit-sig.c
rather than introducing it. No introducing commit could be identified
with enough confidence to tag one.

Signed-off-by: Eva Crystal <[email protected]>
---
 boot/Kconfig         | 27 +++++++++++++++++++++++++++
 boot/image-fit-sig.c | 15 +++++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/boot/Kconfig b/boot/Kconfig
index c67dc0ba49..c1dd1de6ed 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -137,6 +137,25 @@ config FIT_SIGNATURE
          format support in this case, enable it using
          CONFIG_LEGACY_IMAGE_FORMAT.
 
+config FIT_REQUIRE_CONFIG_SIGS
+       bool "Fail verification when the control FDT has no /signature node"
+       depends on FIT_SIGNATURE
+       help
+         Without this option both required-signature gates return success
+         when the U-Boot control devicetree contains no "/signature" node.
+         Verified boot is then silently disabled: a FIT image whose
+         signatures are absent, malformed or invalid verifies successfully
+         and the only indication is a debug() message, which is compiled
+         out of a normal build.
+
+         Enable this option to treat a missing "/signature" node, and a
+         "/signature" node which holds no keys marked required="conf", as a
+         verification failure instead.
+
+         Say N if the same U-Boot binary must also run in setups which carry
+         no keys, or which enable FIT_SIGNATURE only for image hash
+         integrity checking rather than for signature enforcement.
+
 config FIT_SIGNATURE_MAX_SIZE
        hex "Max size of signed FIT structures"
        depends on FIT_SIGNATURE
@@ -259,6 +278,14 @@ config SPL_FIT_SIGNATURE_MAX_SIZE
          device memory. Assure this size does not extend past expected storage
          space.
 
+config SPL_FIT_REQUIRE_CONFIG_SIGS
+       bool "Fail verification when the SPL control FDT has no /signature node"
+       depends on SPL_FIT_SIGNATURE
+       select FIT_REQUIRE_CONFIG_SIGS
+       help
+         Enable the FIT_REQUIRE_CONFIG_SIGS behaviour in SPL. See the help text
+         of FIT_REQUIRE_CONFIG_SIGS for details.
+
 config SPL_LOAD_FIT
        bool "Enable SPL loading U-Boot as a FIT (basic fitImage features)"
        depends on SPL
diff --git a/boot/image-fit-sig.c b/boot/image-fit-sig.c
index a0c50bba4c..06ec0f39d8 100644
--- a/boot/image-fit-sig.c
+++ b/boot/image-fit-sig.c
@@ -201,6 +201,11 @@ int fit_image_verify_required_sigs(const void *fit, int 
image_noffset,
        *no_sigsp = 1;
        key_node = fdt_subnode_offset(key_blob, 0, FIT_SIG_NODENAME);
        if (key_node < 0) {
+               if (CONFIG_IS_ENABLED(FIT_REQUIRE_CONFIG_SIGS)) {
+                       printf("No signature node in control FDT: %s\n",
+                              fdt_strerror(key_node));
+                       return -ENOENT;
+               }
                debug("%s: No signature node found: %s\n", __func__,
                      fdt_strerror(key_node));
                return 0;
@@ -684,6 +689,11 @@ static int fit_config_verify_required_keys(const void 
*fit, int conf_noffset,
        /* Work out what we need to verify */
        key_node = fdt_subnode_offset(key_blob, 0, FIT_SIG_NODENAME);
        if (key_node < 0) {
+               if (CONFIG_IS_ENABLED(FIT_REQUIRE_CONFIG_SIGS)) {
+                       printf("No signature node in control FDT: %s\n",
+                              fdt_strerror(key_node));
+                       return -ENOENT;
+               }
                debug("%s: No signature node found: %s\n", __func__,
                      fdt_strerror(key_node));
                return 0;
@@ -735,6 +745,11 @@ static int fit_config_verify_required_keys(const void 
*fit, int conf_noffset,
                return -EPERM;
        }
 
+       if (!reqd_sigs && CONFIG_IS_ENABLED(FIT_REQUIRE_CONFIG_SIGS)) {
+               printf("No required keys found for configuration 
verification\n");
+               return -EPERM;
+       }
+
        return 0;
 }
 
-- 
2.53.0

Reply via email to