[PATCH 3/3] test: fit: verify dm-verity roothash is covered by the config signature

Simon Glass sjg at chromium.org
Tue Jul 14 14:17:11 CEST 2026


Hi Daniel,

On 2026-07-12T00:33:05, Daniel Golle <daniel at makrotopia.org> wrote:
> test: fit: verify dm-verity roothash is covered by the config signature
>
> A dm-verity protected filesystem image is not hashed by U-Boot; its
> integrity is delegated to the kernel, which trusts the roothash taken
> from the FIT dm-verity subnode. For that chain of trust to hold, the
> roothash (and salt) must be part of the region covered by the
> configuration signature, otherwise an attacker can replace both the
> filesystem and the roothash while keeping the signature valid.
>
> Add two independent checks of this property:
>
>  - test/py/tests/test_fit_verity_sign.py signs a configuration that
>    references a filesystem image carrying a dm-verity subnode, then
>    confirms that tampering the roothash or the salt is rejected by
>    fit_check_sign. A control that tampers a byte known to be signed
>    proves the check can fail.
>
>  - test/boot/fit_verity.c gains a runtime unit test that builds the
>    exact node list the configuration signature is computed over,
>    turns it into hashed regions and checks both that the roothash
> [...]
>
> boot/image-fit-sig.c                  |  25 +++--
>  include/image.h                       |  25 +++++
>  test/boot/fit_verity.c                | 194 ++++++++++++++++++++++++++++++++++
>  test/py/tests/test_fit_verity_sign.py | 162 ++++++++++++++++++++++++++++
>  4 files changed, 399 insertions(+), 7 deletions(-)

Somehow I didn't get this email, but I'll try to reply here.

> diff --git a/boot/image-fit-sig.c b/boot/image-fit-sig.c
> @@ -340,8 +340,19 @@ static int fit_config_add_hash(const void *fit, int image_noffset,
> +#if CONFIG_IS_ENABLED(UNIT_TEST)
> +#define VISIBLE_IF_UT
> +#else
> +#define VISIBLE_IF_UT static
> +#endif

Tom commented on this, but I'll just add this. Linux has
VISIBLE_IF_KUNIT but in U-Boot so far we just stop the static when the
function is needed elsewhere. LTO can be used to avoid the code-size
increase, for platforms that want it.


> diff --git a/test/boot/fit_verity.c b/test/boot/fit_verity.c
> @@ -304,3 +309,192 @@ static int fit_verity_test_bad_blocksize(struct unit_test_state *uts)
> + count = fdt_find_regions(buf, node_inc, count, NULL, 0, fdt_regions,
> + ARRAY_SIZE(fdt_regions) - 1, region_path,
> + sizeof(region_path), 0);
> + ut_assert(count > 0);

fdt_find_regions() can return a count larger than the max passed in,
meaning the region array was exhausted (see the 'count >= max_regions -
1' check in fit_config_check_sig()). If that ever happens here,
fit_region_make_list() reads past the filled entries. Please can you
assert that count is within the array size, matching the real
verification path?

> diff --git a/test/boot/fit_verity.c b/test/boot/fit_verity.c
> @@ -304,3 +309,192 @@ static int fit_verity_test_bad_blocksize(struct unit_test_state *uts)
> + /* Tampering the roothash must change the signed hash. */
> + ((u8 *)digest)[0] ^= 0xff;

You already have digest_off, so you could write to buf[digest_off]
instead of casting away the const from fdt_getprop(). Both work since
buf is writable, but avoiding the cast is cleaner.

> diff --git a/test/boot/fit_verity.c b/test/boot/fit_verity.c
> @@ -304,3 +309,192 @@ static int fit_verity_test_bad_blocksize(struct unit_test_state *uts)
> + digest = fdt_getprop(buf, verity_node, FIT_VERITY_DIGEST_PROP,
> +      &digest_len);

The python test also tampers the salt, but the unit test only checks
the digest. Since both properties sit in the same dm-verity node the
coverage result is the same, so I don't feel strongly, but a one-line
comment noting that the digest check stands in for the whole node would
make the asymmetry clearer. What do you think?

Regards,
Simon


More information about the U-Boot mailing list