Build a control devicetree with no "/signature" node and an unsigned FIT, then check that the boot is refused when CONFIG_FIT_REQUIRE_IMAGE_SIGS is enabled, and that the historical fail-open behaviour is kept when it is not.
The missing node is reported whether or not the option is enabled, so the warning is expected in both cases and only the boot outcome differs. Cc: Jonas Karlman <[email protected]> Signed-off-by: Eva Crystal <[email protected]> --- test/py/tests/test_vboot.py | 109 ++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/test/py/tests/test_vboot.py b/test/py/tests/test_vboot.py index fd63d8b4e0..4e361bf18a 100644 --- a/test/py/tests/test_vboot.py +++ b/test/py/tests/test_vboot.py @@ -950,3 +950,112 @@ def test_fdt_add_pubkey(ubman, name, sha_algo, padding, sign_options, algo_arg): # keys created in test_vboot test test_add_pubkey(sha_algo, padding, sign_options) + + [email protected]('sandbox') [email protected]('fit_signature') [email protected]('dtc') [email protected]('fdtget') [email protected]('openssl') +def test_vboot_no_sig_node(ubman): + """Test a control FDT which contains no /signature node. + + fit_image_verify_required_sigs() looks up the "/signature" node of the + U-Boot control devicetree to work out which keys are marked required. + When that node is absent there are no required keys, so nothing + downstream can fail the image and a FIT whose signatures are absent or + invalid verifies successfully. + + The missing node is reported with log_warning() whether or not + CONFIG_FIT_REQUIRE_IMAGE_SIGS is enabled, so the warning is expected in + both cases and only the boot outcome differs. With the option the image + gate fails and the boot must be refused. Without it the historical + fail-open behaviour is kept, so that boards using FIT_SIGNATURE only for + image hash integrity keep booting. + + This works using sandbox only as it needs to control the device tree + used by U-Boot. + """ + sha_algo = 'sha256' + + def run_bootm(test_type, expect_strings, boots): + """Run a 'bootm' command in U-Boot. + + Args: + test_type: A string identifying the test type. + expect_strings: A list of strings which are all expected in the + output. + boots: True if the image is expected to boot, False if the boot + is expected to be refused. + """ + ubman.restart_uboot() + with ubman.log.section('Verified boot %s %s' % (sha_algo, test_type)): + output = ubman.run_command_list( + ['host load hostfs - 100 %s' % fit, + 'fdt addr 100', + 'bootm 100']) + text = ''.join(output) + for expect_string in expect_strings: + assert expect_string in text + if boots: + assert 'sandbox: continuing, as we cannot run' in text + else: + assert 'sandbox: continuing, as we cannot run' not in text + + tmpdir = os.path.join(ubman.config.result_dir, 'no-sig-node') + '/' + if not os.path.exists(tmpdir): + os.mkdir(tmpdir) + datadir = ubman.config.source_dir + '/test/py/tests/vboot/' + fit = '%stest.fit' % tmpdir + mkimage = ubman.config.build_dir + '/tools/mkimage' + dtc_args = '-I dts -O dtb -i %s' % tmpdir + dtb = '%ssandbox-u-boot.dtb' % tmpdir + + bcfg = ubman.config.buildconfig + require_image_sigs = bcfg.get('config_fit_require_image_sigs', False) + + # Create a kernel image filled with zeroes + with open('%stest-kernel.bin' % tmpdir, 'wb') as fd: + fd.write(500 * b'\0') + + # We need to use our own device tree file. Remember to restore it + # afterwards. + old_dtb = ubman.config.dtb + try: + ubman.config.dtb = dtb + + # Compile the control devicetree. sandbox-u-boot.dts holds no keys, + # and mkimage is deliberately not asked to add any, so the resulting + # blob has no /signature node at all. + dtc('sandbox-kernel.dts', ubman, dtc_args, datadir, tmpdir, dtb) + dtc('sandbox-u-boot.dts', ubman, dtc_args, datadir, tmpdir, dtb) + + # Confirm the premise of the test: no /signature node is present. + out = utils.run_and_log(ubman, 'fdtget -l %s /' % dtb) + assert 'signature' not in out + + # Build a FIT whose configuration signature has no 'value', i.e. it + # is unsigned. + ubman.log.action('%s: Test unsigned FIT with no keys in control FDT' + % sha_algo) + make_fit('sign-configs-%s.its' % sha_algo, ubman, mkimage, dtc_args, + datadir, fit) + + # The missing "/signature" node is reported either way, so the + # warning is expected in both branches and only the outcome differs. + warning = 'No signature node in control FDT' + if require_image_sigs: + # The image gate fails and the boot is refused. + run_bootm('no signature node', + [warning, 'Unable to verify required signature'], + False) + else: + # Fail-open is kept: the image still verifies and the board + # boots, but the condition is no longer silent. + run_bootm('no signature node', + [warning, 'Verifying Hash Integrity'], + True) + finally: + # Go back to the original U-Boot with the correct dtb. + ubman.config.dtb = old_dtb + ubman.restart_uboot() -- 2.53.0
