[PATCH v3 0/3] Add support for multiple required keys

This patch series adds the support for multiple required keys in U-Boot DTB with test support.
Changes in v3: - Replaced 'u-boot' with 'U-Boot' in commit messages. - Added an explicit print message to indicate that no required signature was verified.
Changes in v2 (thanks for the feedback Simon and Rasmus): - Introduce a policy variable in U-boot DTB to control whether any or all required keys must have signed configuration. - Added tests to cover any or all required keys policy. - Updated signature.txt to include required-mode policy information.
Thirupathaiah Annapureddy (3): vboot: add DTB policy for supporting multiple required conf keys test: vboot: add tests for multiple required keys doc: verified-boot: add required-mode information
common/image-fit-sig.c | 32 ++++++++++++++++++++++--- doc/uImage.FIT/signature.txt | 14 +++++++++++ test/py/tests/test_vboot.py | 46 ++++++++++++++++++++++++++++++++++-- 3 files changed, 87 insertions(+), 5 deletions(-)

Currently FIT image must be signed by all required conf keys. This means Verified Boot fails if there is a signature verification failure using any required key in U-Boot DTB.
This patch introduces a new policy in DTB that can be set to any required conf key. This means if verified boot passes with one of the required keys, U-Boot will continue the OS hand off.
There were prior attempts to address this: https://lists.denx.de/pipermail/u-boot/2019-April/366047.html The above patch was failing "make tests". https://lists.denx.de/pipermail/u-boot/2020-January/396629.html
Signed-off-by: Thirupathaiah Annapureddy thiruan@linux.microsoft.com Reviewed-by: Simon Glass sjg@chromium.org ---
Changes in v3: - Replaced 'u-boot' with 'U-Boot' in commit message. - Added an explicit print message to indicate that no required signature was verified.
Changes in v2: - Modify fit_config_verify_required_sigs() to process required-mode policy variable in U-boot DTB.
common/image-fit-sig.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-)
diff --git a/common/image-fit-sig.c b/common/image-fit-sig.c index cc1967109e..5401d9411b 100644 --- a/common/image-fit-sig.c +++ b/common/image-fit-sig.c @@ -416,6 +416,10 @@ int fit_config_verify_required_sigs(const void *fit, int conf_noffset, { int noffset; int sig_node; + int verified = 0; + int reqd_sigs = 0; + bool reqd_policy_all = true; + const char *reqd_mode;
/* Work out what we need to verify */ sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME); @@ -425,6 +429,14 @@ int fit_config_verify_required_sigs(const void *fit, int conf_noffset, return 0; }
+ /* Get required-mode policy property from DTB */ + reqd_mode = fdt_getprop(sig_blob, sig_node, "required-mode", NULL); + if (reqd_mode && !strcmp(reqd_mode, "any")) + reqd_policy_all = false; + + debug("%s: required-mode policy set to '%s'\n", __func__, + reqd_policy_all ? "all" : "any"); + fdt_for_each_subnode(noffset, sig_blob, sig_node) { const char *required; int ret; @@ -433,15 +445,29 @@ int fit_config_verify_required_sigs(const void *fit, int conf_noffset, NULL); if (!required || strcmp(required, "conf")) continue; + + reqd_sigs++; + ret = fit_config_verify_sig(fit, conf_noffset, sig_blob, noffset); if (ret) { - printf("Failed to verify required signature '%s'\n", - fit_get_name(sig_blob, noffset, NULL)); - return ret; + if (reqd_policy_all) { + printf("Failed to verify required signature '%s'\n", + fit_get_name(sig_blob, noffset, NULL)); + return ret; + } + } else { + verified++; + if (!reqd_policy_all) + break; } }
+ if (reqd_sigs && !verified) { + printf("Failed to verify 'any' of the required signature(s)\n"); + return -EPERM; + } + return 0; }

On Sun, Aug 16, 2020 at 11:01:09PM -0700, Thirupathaiah Annapureddy wrote:
Currently FIT image must be signed by all required conf keys. This means Verified Boot fails if there is a signature verification failure using any required key in U-Boot DTB.
This patch introduces a new policy in DTB that can be set to any required conf key. This means if verified boot passes with one of the required keys, U-Boot will continue the OS hand off.
There were prior attempts to address this: https://lists.denx.de/pipermail/u-boot/2019-April/366047.html The above patch was failing "make tests". https://lists.denx.de/pipermail/u-boot/2020-January/396629.html
Signed-off-by: Thirupathaiah Annapureddy thiruan@linux.microsoft.com Reviewed-by: Simon Glass sjg@chromium.org
Applied to u-boot/master, thanks!

This patch adds vboot tests to verify the support for multiple required keys using new required-mode DTB policy.
This patch also fixes existing test where dev key is assumed to be marked as not required, although it is marked as required.
Note that this patch re-added sign_fit_norequire(). sign_fit_norequire() was removed as part of the following: commit b008677daf2a ("test: vboot: Fix pylint errors"). This patch leverages sign_fit_norequire() to fix the existing bug.
Signed-off-by: Thirupathaiah Annapureddy thiruan@linux.microsoft.com Reviewed-by: Simon Glass sjg@chromium.org ---
Changes in v3: - Modified commit message to reference earlier commit the right way.
Changes in v2: - Added tests to cover any or all required keys policy.
test/py/tests/test_vboot.py | 46 +++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-)
diff --git a/test/py/tests/test_vboot.py b/test/py/tests/test_vboot.py index 6b998cfd70..e45800d94c 100644 --- a/test/py/tests/test_vboot.py +++ b/test/py/tests/test_vboot.py @@ -126,6 +126,23 @@ def test_vboot(u_boot_console, sha_algo, padding, sign_options, required): cons.log.action('%s: Sign images' % sha_algo) util.run_and_log(cons, args)
+ def sign_fit_norequire(sha_algo, options): + """Sign the FIT + + Signs the FIT and writes the signature into it. It also writes the + public key into the dtb. It does not mark key as 'required' in dtb. + + Args: + sha_algo: Either 'sha1' or 'sha256', to select the algorithm to + use. + options: Options to provide to mkimage. + """ + args = [mkimage, '-F', '-k', tmpdir, '-K', dtb, fit] + if options: + args += options.split(' ') + cons.log.action('%s: Sign images' % sha_algo) + util.run_and_log(cons, args) + def replace_fit_totalsize(size): """Replace FIT header's totalsize with something greater.
@@ -279,15 +296,40 @@ def test_vboot(u_boot_console, sha_algo, padding, sign_options, required): # Build the FIT with dev key (keys NOT required). This adds the # signature into sandbox-u-boot.dtb, NOT marked 'required'. make_fit('sign-configs-%s%s.its' % (sha_algo, padding)) - sign_fit(sha_algo, sign_options) + sign_fit_norequire(sha_algo, sign_options)
# So now sandbox-u-boot.dtb two signatures, for the prod and dev keys. # Only the prod key is set as 'required'. But FIT we just built has - # a dev signature only (sign_fit() overwrites the FIT). + # a dev signature only (sign_fit_norequire() overwrites the FIT). # Try to boot the FIT with dev key. This FIT should not be accepted by # U-Boot because the prod key is required. run_bootm(sha_algo, 'required key', '', False)
+ # Build the FIT with dev key (keys required) and sign it. This puts the + # signature into sandbox-u-boot.dtb, marked 'required'. + make_fit('sign-configs-%s%s.its' % (sha_algo, padding)) + sign_fit(sha_algo, sign_options) + + # Set the required-mode policy to "any". + # So now sandbox-u-boot.dtb two signatures, for the prod and dev keys. + # Both the dev and prod key are set as 'required'. But FIT we just built has + # a dev signature only (sign_fit() overwrites the FIT). + # Try to boot the FIT with dev key. This FIT should be accepted by + # U-Boot because the dev key is required and policy is "any" required key. + util.run_and_log(cons, 'fdtput -t s %s /signature required-mode any' % + (dtb)) + run_bootm(sha_algo, 'multi required key', 'dev+', True) + + # Set the required-mode policy to "all". + # So now sandbox-u-boot.dtb two signatures, for the prod and dev keys. + # Both the dev and prod key are set as 'required'. But FIT we just built has + # a dev signature only (sign_fit() overwrites the FIT). + # Try to boot the FIT with dev key. This FIT should not be accepted by + # U-Boot because the prod key is required and policy is "all" required key + util.run_and_log(cons, 'fdtput -t s %s /signature required-mode all' % + (dtb)) + run_bootm(sha_algo, 'multi required key', '', False) + cons = u_boot_console tmpdir = cons.config.result_dir + '/' datadir = cons.config.source_dir + '/test/py/tests/vboot/'

On Sun, Aug 16, 2020 at 11:01:10PM -0700, Thirupathaiah Annapureddy wrote:
This patch adds vboot tests to verify the support for multiple required keys using new required-mode DTB policy.
This patch also fixes existing test where dev key is assumed to be marked as not required, although it is marked as required.
Note that this patch re-added sign_fit_norequire(). sign_fit_norequire() was removed as part of the following: commit b008677daf2a ("test: vboot: Fix pylint errors"). This patch leverages sign_fit_norequire() to fix the existing bug.
Signed-off-by: Thirupathaiah Annapureddy thiruan@linux.microsoft.com Reviewed-by: Simon Glass sjg@chromium.org
Applied to u-boot/master, thanks!

Add documentation about 'required-mode' property in /signature node in U-Boot's control FDT.
Signed-off-by: Thirupathaiah Annapureddy thiruan@linux.microsoft.com Reviewed-by: Simon Glass sjg@chromium.org ---
Changes in v3: - Added commit description to address checkpatch warning.
Changes in v2: - New.
doc/uImage.FIT/signature.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/doc/uImage.FIT/signature.txt b/doc/uImage.FIT/signature.txt index d4afd755e9..a3455889ed 100644 --- a/doc/uImage.FIT/signature.txt +++ b/doc/uImage.FIT/signature.txt @@ -386,6 +386,20 @@ that might be used by the target needs to be signed with 'required' keys.
This happens automatically as part of a bootm command when FITs are used.
+For Signed Configurations, the default verification behavior can be changed by +the following optional property in /signature node in U-Boot's control FDT. + +- required-mode: Valid values are "any" to allow verified boot to succeed if +the selected configuration is signed by any of the 'required' keys, and "all" +to allow verified boot to succeed if the selected configuration is signed by +all of the 'required' keys. + +This property can be added to a binary device tree using fdtput as shown in +below examples:: + + fdtput -t s control.dtb /signature required-mode any + fdtput -t s control.dtb /signature required-mode all +
Enabling FIT Verification -------------------------

On Sun, Aug 16, 2020 at 11:01:11PM -0700, Thirupathaiah Annapureddy wrote:
Add documentation about 'required-mode' property in /signature node in U-Boot's control FDT.
Signed-off-by: Thirupathaiah Annapureddy thiruan@linux.microsoft.com Reviewed-by: Simon Glass sjg@chromium.org
Applied to u-boot/master, thanks!
participants (2)
-
Thirupathaiah Annapureddy
-
Tom Rini