[PATCH v2 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 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 | 30 ++++++++++++++++++++--- doc/uImage.FIT/signature.txt | 14 +++++++++++ test/py/tests/test_vboot.py | 46 ++++++++++++++++++++++++++++++++++-- 3 files changed, 85 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 ---
Changes in v2: - Modify fit_config_verify_required_sigs() to process required-mode policy variable in U-boot DTB.
common/image-fit-sig.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-)
diff --git a/common/image-fit-sig.c b/common/image-fit-sig.c index cc1967109e..d9b1c93a9b 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,27 @@ 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) + return -EPERM; + return 0; }

Hi Thirupathaiah,
On Fri, 17 Jul 2020 at 21:20, Thirupathaiah Annapureddy thiruan@linux.microsoft.com 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.
U-Boot
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
Changes in v2:
- Modify fit_config_verify_required_sigs() to process required-mode
policy variable in U-boot DTB.
common/image-fit-sig.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
Please see below
diff --git a/common/image-fit-sig.c b/common/image-fit-sig.c index cc1967109e..d9b1c93a9b 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,27 @@ 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));
I think we should keep this message outside the if(). Otherwise there is no indication what is going on.
return ret;
}
} else {
verified++;
if (!reqd_policy_all)
break; } }
if (reqd_sigs && !verified)
I think we need a message here, indicating that no signature was verified.
return -EPERM;
return 0;
}
-- 2.25.2

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 commit: b008677daf2a9dc0335260c7c4e24390487fe0ca (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 ---
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 Fri, 17 Jul 2020 at 21:20, Thirupathaiah Annapureddy thiruan@linux.microsoft.com 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 commit: b008677daf2a9dc0335260c7c4e24390487fe0ca (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
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(-)
Reviewed-by: Simon Glass sjg@chromium.org

Signed-off-by: Thirupathaiah Annapureddy thiruan@linux.microsoft.com ---
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 -------------------------

Hi Thirupathaiah,
On Fri, 17 Jul 2020 at 21:20, Thirupathaiah Annapureddy thiruan@linux.microsoft.com wrote:
Signed-off-by: Thirupathaiah Annapureddy thiruan@linux.microsoft.com
Changes in v2:
- New
doc/uImage.FIT/signature.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org
But I think we need a new mkimage option to set the required-mode
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
-- 2.25.2

On 7/28/2020 11:58 AM, Simon Glass wrote:
Hi Thirupathaiah,
On Fri, 17 Jul 2020 at 21:20, Thirupathaiah Annapureddy thiruan@linux.microsoft.com wrote:
Signed-off-by: Thirupathaiah Annapureddy thiruan@linux.microsoft.com
Changes in v2:
- New
doc/uImage.FIT/signature.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org
But I think we need a new mkimage option to set the required-mode
Is it okay if I do mkimage option change as part of a different patch/ patch series?
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
-- 2.25.2

Hi Thirupathaiah,
On Sun, 16 Aug 2020 at 22:09, Thirupathaiah Annapureddy thiruan@linux.microsoft.com wrote:
On 7/28/2020 11:58 AM, Simon Glass wrote:
Hi Thirupathaiah,
On Fri, 17 Jul 2020 at 21:20, Thirupathaiah Annapureddy thiruan@linux.microsoft.com wrote:
Signed-off-by: Thirupathaiah Annapureddy thiruan@linux.microsoft.com
Changes in v2:
- New
doc/uImage.FIT/signature.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org
But I think we need a new mkimage option to set the required-mode
Is it okay if I do mkimage option change as part of a different patch/ patch series?
That's fine with me.
Regards, SImon
participants (2)
-
Simon Glass
-
Thirupathaiah Annapureddy