Hi Philippe, On Fri, 25 Feb 2022 at 07:58, Philippe Reynes <philippe.rey...@softathome.com> wrote: > > Adds test units for the pre-load header signature. > > Signed-off-by: Philippe Reynes <philippe.rey...@softathome.com> > --- > test/py/tests/test_vboot.py | 125 +++++++++++++++--- > test/py/tests/vboot/sandbox-binman-pss.dts | 25 ++++ > test/py/tests/vboot/sandbox-binman.dts | 24 ++++ > .../tests/vboot/sandbox-u-boot-global-pss.dts | 28 ++++ > test/py/tests/vboot/sandbox-u-boot-global.dts | 27 ++++ > test/py/tests/vboot/simple-images.its | 36 +++++ > 6 files changed, 249 insertions(+), 16 deletions(-) > create mode 100644 test/py/tests/vboot/sandbox-binman-pss.dts > create mode 100644 test/py/tests/vboot/sandbox-binman.dts > create mode 100644 test/py/tests/vboot/sandbox-u-boot-global-pss.dts > create mode 100644 test/py/tests/vboot/sandbox-u-boot-global.dts > create mode 100644 test/py/tests/vboot/simple-images.its > > diff --git a/test/py/tests/test_vboot.py b/test/py/tests/test_vboot.py > index ac8ed9f114..a4a2bb2955 100644 > --- a/test/py/tests/test_vboot.py > +++ b/test/py/tests/test_vboot.py > @@ -35,19 +35,21 @@ import vboot_evil
please add to the comment at the top of the file since you have added a new way > # Only run the full suite on a few combinations, since it doesn't add any > more > # test coverage. > TESTDATA = [ > - ['sha1-basic', 'sha1', '', None, False, True, False], > - ['sha1-pad', 'sha1', '', '-E -p 0x10000', False, False, False], > - ['sha1-pss', 'sha1', '-pss', None, False, False, False], > - ['sha1-pss-pad', 'sha1', '-pss', '-E -p 0x10000', False, False, False], > - ['sha256-basic', 'sha256', '', None, False, False, False], > - ['sha256-pad', 'sha256', '', '-E -p 0x10000', False, False, False], > - ['sha256-pss', 'sha256', '-pss', None, False, False, False], > - ['sha256-pss-pad', 'sha256', '-pss', '-E -p 0x10000', False, False, > False], > - ['sha256-pss-required', 'sha256', '-pss', None, True, False, False], > - ['sha256-pss-pad-required', 'sha256', '-pss', '-E -p 0x10000', True, > True, False], > - ['sha384-basic', 'sha384', '', None, False, False, False], > - ['sha384-pad', 'sha384', '', '-E -p 0x10000', False, False, False], > - ['algo-arg', 'algo-arg', '', '-o sha256,rsa2048', False, False, True], > + ['sha1-basic', 'sha1', '', None, False, True, False, False], > + ['sha1-pad', 'sha1', '', '-E -p 0x10000', False, False, False, False], > + ['sha1-pss', 'sha1', '-pss', None, False, False, False, False], > + ['sha1-pss-pad', 'sha1', '-pss', '-E -p 0x10000', False, False, False, > False], > + ['sha256-basic', 'sha256', '', None, False, False, False, False], > + ['sha256-pad', 'sha256', '', '-E -p 0x10000', False, False, False, > False], > + ['sha256-pss', 'sha256', '-pss', None, False, False, False, False], > + ['sha256-pss-pad', 'sha256', '-pss', '-E -p 0x10000', False, False, > False, False], > + ['sha256-pss-required', 'sha256', '-pss', None, True, False, False, > False], > + ['sha256-pss-pad-required', 'sha256', '-pss', '-E -p 0x10000', True, > True, False, False], > + ['sha384-basic', 'sha384', '', None, False, False, False, False], > + ['sha384-pad', 'sha384', '', '-E -p 0x10000', False, False, False, > False], > + ['algo-arg', 'algo-arg', '', '-o sha256,rsa2048', False, False, True, > False], > + ['sha256-global-sign', 'sha256', '', '', False, False, False, True], > + ['sha256-global-sign-pss', 'sha256', '-pss', '', False, False, False, > True], > ] > > @pytest.mark.boardspec('sandbox') > @@ -56,10 +58,10 @@ TESTDATA = [ > @pytest.mark.requiredtool('fdtget') > @pytest.mark.requiredtool('fdtput') > @pytest.mark.requiredtool('openssl') > -@pytest.mark.parametrize("name,sha_algo,padding,sign_options,required,full_test,algo_arg", > +@pytest.mark.parametrize("name,sha_algo,padding,sign_options,required,full_test,algo_arg,global_sign", > TESTDATA) > def test_vboot(u_boot_console, name, sha_algo, padding, sign_options, > required, > - full_test, algo_arg): > + full_test, algo_arg, global_sign): > """Test verified boot signing with mkimage and verification with 'bootm'. > > This works using sandbox only as it needs to update the device tree used > @@ -81,6 +83,29 @@ def test_vboot(u_boot_console, name, sha_algo, padding, > sign_options, required, > util.run_and_log(cons, 'dtc %s %s%s -O dtb ' > '-o %s%s' % (dtc_args, datadir, dts, tmpdir, dtb)) > > + def dtc_options(dts, options): > + """Run the device tree compiler to compile a .dts file > + > + The output file will be the same as the input file but with a .dtb > + extension. > + > + Args: > + dts: Device tree file to compile. > + options: Options provided to the compiler. > + """ > + dtb = dts.replace('.dts', '.dtb') > + util.run_and_log(cons, 'dtc %s %s%s -O dtb ' > + '-o %s%s %s' % (dtc_args, datadir, dts, tmpdir, > dtb, options)) > + > + def run_binman(dtb): > + """Run binman to build an image > + > + Args: > + dtb: Device tree file used as input file. > + """ > + util.run_and_log(cons, [binman, 'build', '-d', "%s/%s" % > (tmpdir,dtb), > + '-a', "key-path=%s" % tmpdir, '-O', tmpdir, > '-I', tmpdir]) > + > def run_bootm(sha_algo, test_type, expect_string, boots, fit=None): > """Run a 'bootm' command U-Boot. > > @@ -139,6 +164,23 @@ def test_vboot(u_boot_console, name, sha_algo, padding, > sign_options, required, > cons.log.action('%s: Sign images' % sha_algo) > util.run_and_log(cons, args) > > + def sign_fit_dtb(sha_algo, options, dtb): > + """Sign the FIT > + > + Signs the FIT and writes the signature into it. It also writes the > + public key into the 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, '-r', fit] > + if options: > + args += options.split(' ') > + cons.log.action('%s: Sign images' % sha_algo) > + util.run_and_log(cons, args) > + > def sign_fit_norequire(sha_algo, options): > """Sign the FIT > > @@ -176,6 +218,11 @@ def test_vboot(u_boot_console, name, sha_algo, padding, > sign_options, required, > handle.write(struct.pack(">I", size)) > return struct.unpack(">I", total_size)[0] > > + def corrupt_file(fit,offset,value): spaces after , also please comment the function > + with open(fit, 'r+b') as handle: > + handle.seek(offset) > + handle.write(struct.pack(">I", value)) > + > def create_rsa_pair(name): > """Generate a new RSA key paid and certificate > > @@ -374,6 +421,49 @@ def test_vboot(u_boot_console, name, sha_algo, padding, > sign_options, required, > (dtb)) > run_bootm(sha_algo, 'multi required key', '', False) > > + def test_global_sign(sha_algo, padding, sign_options): > + """Test global image signature with the given hash algorithm and > padding. > + > + Args: > + sha_algo: Either 'sha1' or 'sha256', to select the algorithm to > use > + padding: Either '' or '-pss', to select the padding to use for > the > + rsa signature algorithm. > + """ > + > + dtb = '%ssandbox-u-boot-global%s.dtb' % (tmpdir, padding) > + cons.config.dtb = dtb > + > + # Compile our device tree files for kernel and U-Boot. These are > + # regenerated here since mkimage will modify them (by adding a > + # public key) below. > + dtc('sandbox-kernel.dts') > + dtc_options('sandbox-u-boot-global%s.dts' % padding, '-p 1024') > + > + # Build the FIT with dev key (keys NOT required). This adds the > + # signature into sandbox-u-boot.dtb, NOT marked 'required'. > + make_fit('simple-images.its') > + sign_fit_dtb(sha_algo, '', dtb) > + > + # Build the dtb for binman that define the pre-load header > + # with the global sigature. > + dtc('sandbox-binman%s.dts' % padding) > + > + # Run binman to create the final image with the not signed fit > + # and the pre-load header that contains the global signature. > + run_binman('sandbox-binman%s.dtb' % padding) > + > + # Check that the signature is correctly verified by u-boot > + run_bootm(sha_algo, 'global image signature', 'signature check has > succeed', True, "%ssandbox.img" % tmpdir) make sure to wrap to 80 chars > + > + # Corrupt the image (just one byte after the pre-load header) > + corrupt_file("%ssandbox.img" % tmpdir, 4096, 255); > + > + # Check that the signature verification fails > + run_bootm(sha_algo, 'global image signature', 'signature check has > failed', False, "%ssandbox.img" % tmpdir) > + > + # Check that the boot fails if the global signature is not provided > + run_bootm(sha_algo, 'global image signature', 'signature is > mandatory', False) > + > cons = u_boot_console > tmpdir = os.path.join(cons.config.result_dir, name) + '/' > if not os.path.exists(tmpdir): > @@ -381,6 +471,7 @@ def test_vboot(u_boot_console, name, sha_algo, padding, > sign_options, required, > datadir = cons.config.source_dir + '/test/py/tests/vboot/' > fit = '%stest.fit' % tmpdir > mkimage = cons.config.build_dir + '/tools/mkimage' > + binman = cons.config.source_dir + '/tools/binman/binman' > fit_check_sign = cons.config.build_dir + '/tools/fit_check_sign' > dtc_args = '-I dts -O dtb -i %s' % tmpdir > dtb = '%ssandbox-u-boot.dtb' % tmpdir > @@ -403,7 +494,9 @@ def test_vboot(u_boot_console, name, sha_algo, padding, > sign_options, required, > # afterwards. > old_dtb = cons.config.dtb > cons.config.dtb = dtb > - if required: > + if global_sign: > + test_global_sign(sha_algo, padding, sign_options) do you not want to also test the normal signature? > + elif required: > test_required_key(sha_algo, padding, sign_options) > else: > test_with_algo(sha_algo, padding, sign_options) > diff --git a/test/py/tests/vboot/sandbox-binman-pss.dts > b/test/py/tests/vboot/sandbox-binman-pss.dts > new file mode 100644 > index 0000000000..56e3a42fa6 > --- /dev/null [..] Regards, Simon