From: Klaus Heinrich Kiwi <klaus@linux.vnet.ibm.com>
To: openembedded-core@lists.openembedded.org
Cc: andrew@aj.id.au, Klaus Heinrich Kiwi <klaus@linux.vnet.ibm.com>,
openbmc@lists.ozlabs.org
Subject: [PATCH 4/4] oe-selftest: Add U-Boot fitImage signing testcases
Date: Mon, 15 Mar 2021 13:58:06 -0300 [thread overview]
Message-ID: <20210315165806.1633-5-klaus@linux.vnet.ibm.com> (raw)
In-Reply-To: <20210315165806.1633-1-klaus@linux.vnet.ibm.com>
Derived from the similar kernel fitImage sign testcase, the U-Boot
fitImage testcases will test both the standalone (only SPL_SIGN_ENABLE
set) as well as cascaded (both UBOOT_SIGN_ENABLE as well as
SPL_SIGN_ENABLE) scenarios.
Signed-off-by: Klaus Heinrich Kiwi <klaus@linux.vnet.ibm.com>
---
meta/lib/oeqa/selftest/cases/fitimage.py | 293 +++++++++++++++++++++++
1 file changed, 293 insertions(+)
diff --git a/meta/lib/oeqa/selftest/cases/fitimage.py b/meta/lib/oeqa/selftest/cases/fitimage.py
index 02692de822..ece1ad460b 100644
--- a/meta/lib/oeqa/selftest/cases/fitimage.py
+++ b/meta/lib/oeqa/selftest/cases/fitimage.py
@@ -231,6 +231,299 @@ UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'"
result = runCmd('grep "### uboot-mkimage signing wrapper message" %s/log.do_assemble_fitimage' % tempdir, ignore_status=True)
self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE_SIGN did not work')
+ def test_sign_standalone_uboot_fit_image(self):
+ """
+ Summary: Check if U-Boot FIT image and Image Tree Source (its) are
+ created and signed correctly for the scenario where only
+ the U-Boot proper fitImage is being signed.
+ Expected: 1) U-Boot its and FIT image are built successfully
+ 2) Scanning the its file indicates signing is enabled
+ as requested by SPL_SIGN_ENABLE (using keys generated
+ via UBOOT_FIT_GENERATE_KEYS)
+ 3) Dumping the FIT image indicates signature values
+ are present
+ 4) Examination of the do_uboot_assemble_fitimage
+ runfile/logfile indicate that UBOOT_MKIMAGE, UBOOT_MKIMAGE_SIGN
+ and SPL_MKIMAGE_SIGN_ARGS are working as expected.
+ Product: oe-core
+ Author: Klaus Heinrich Kiwi <klaus@linux.vnet.ibm.com> based upon
+ work by Paul Eggleton <paul.eggleton@microsoft.com> and
+ Usama Arif <usama.arif@arm.com>
+ """
+ config = """
+# There's no U-boot deconfig with CONFIG_FIT_SIGNATURE yet, so we need at
+# least CONFIG_SPL_LOAD_FIT and CONFIG_SPL_OF_CONTROL set
+MACHINE = "beaglebone-yocto"
+UBOOT_MACHINE = "am57xx_evm_defconfig"
+USER_CLASSES = " test-mkimage-wrapper "
+SPL_SIGN_ENABLE = "1"
+SPL_SIGN_KEYNAME = "spl-oe-selftest"
+SPL_SIGN_KEYDIR = "${TOPDIR}/signing-keys"
+UBOOT_DTB_BINARY = "u-boot.dtb"
+UBOOT_ENTRYPOINT = "0x80000000"
+UBOOT_LOADADDRESS = "0x80000000"
+UBOOT_DTB_LOADADDRESS = "0x82000000"
+UBOOT_ARCH = "arm"
+SPL_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000"
+SPL_MKIMAGE_SIGN_ARGS = "-c 'a smart U-Boot comment'"
+UBOOT_EXTLINUX = "0"
+UBOOT_FIT_GENERATE_KEYS = "1"
+UBOOT_FIT_HASH_ALG = "sha256"
+"""
+ self.write_config(config)
+
+ # this scenario exercises standalone u-boot fitImage sign
+ bitbake("u-boot")
+
+ image_type = "core-image-minimal"
+ deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
+ machine = get_bb_var('MACHINE')
+ fitimage_its_path = os.path.join(deploy_dir_image,
+ "u-boot-its-%s" % (machine,))
+ fitimage_path = os.path.join(deploy_dir_image,
+ "u-boot-fitImage-%s" % (machine,))
+
+ self.assertTrue(os.path.exists(fitimage_its_path),
+ "%s image tree source doesn't exist" % (fitimage_its_path))
+ self.assertTrue(os.path.exists(fitimage_path),
+ "%s FIT image doesn't exist" % (fitimage_path))
+
+ req_itspaths = [
+ ['/', 'images', 'uboot'],
+ ['/', 'images', 'uboot', 'signature'],
+ ['/', 'images', 'fdt'],
+ ['/', 'images', 'fdt', 'signature'],
+ ]
+
+ itspath = []
+ itspaths = []
+ linect = 0
+ sigs = {}
+ with open(fitimage_its_path) as its_file:
+ linect += 1
+ for line in its_file:
+ line = line.strip()
+ if line.endswith('};'):
+ itspath.pop()
+ elif line.endswith('{'):
+ itspath.append(line[:-1].strip())
+ itspaths.append(itspath[:])
+ elif itspath and itspath[-1] == 'signature':
+ itsdotpath = '.'.join(itspath)
+ if not itsdotpath in sigs:
+ sigs[itsdotpath] = {}
+ if not '=' in line or not line.endswith(';'):
+ self.fail('Unexpected formatting in %s sigs section line %d:%s' % (fitimage_its_path, linect, line))
+ key, value = line.split('=', 1)
+ sigs[itsdotpath][key.rstrip()] = value.lstrip().rstrip(';')
+
+ for reqpath in req_itspaths:
+ if not reqpath in itspaths:
+ self.fail('Missing section in its file: %s' % reqpath)
+
+ reqsigvalues_image = {
+ 'algo': '"sha256,rsa2048"',
+ 'key-name-hint': '"spl-oe-selftest"',
+ }
+
+ for itspath, values in sigs.items():
+ reqsigvalues = reqsigvalues_image
+ for reqkey, reqvalue in reqsigvalues.items():
+ value = values.get(reqkey, None)
+ if value is None:
+ self.fail('Missing key "%s" in its file signature section %s' % (reqkey, itspath))
+ self.assertEqual(value, reqvalue)
+
+ # Dump the image to see if it really got signed
+ bitbake("u-boot-tools-native -c addto_recipe_sysroot")
+ result = runCmd('bitbake -e u-boot-tools-native | grep ^RECIPE_SYSROOT_NATIVE=')
+ recipe_sysroot_native = result.output.split('=')[1].strip('"')
+ dumpimage_path = os.path.join(recipe_sysroot_native, 'usr', 'bin', 'dumpimage')
+ result = runCmd('%s -l %s' % (dumpimage_path, fitimage_path))
+ in_signed = None
+ signed_sections = {}
+ for line in result.output.splitlines():
+ if line.startswith((' Image')):
+ in_signed = re.search('\((.*)\)', line).groups()[0]
+ elif re.match(' \w', line):
+ in_signed = None
+ elif in_signed:
+ if not in_signed in signed_sections:
+ signed_sections[in_signed] = {}
+ key, value = line.split(':', 1)
+ signed_sections[in_signed][key.strip()] = value.strip()
+ self.assertIn('uboot', signed_sections)
+ self.assertIn('fdt', signed_sections)
+ for signed_section, values in signed_sections.items():
+ value = values.get('Sign algo', None)
+ self.assertEqual(value, 'sha256,rsa2048:spl-oe-selftest', 'Signature algorithm for %s not expected value' % signed_section)
+ value = values.get('Sign value', None)
+ self.assertEqual(len(value), 512, 'Signature value for section %s not expected length' % signed_section)
+
+ # Check for SPL_MKIMAGE_SIGN_ARGS
+ result = runCmd('bitbake -e u-boot | grep ^T=')
+ tempdir = result.output.split('=', 1)[1].strip().strip('')
+ result = runCmd('grep "a smart U-Boot comment" %s/run.do_uboot_assemble_fitimage' % tempdir, ignore_status=True)
+ self.assertEqual(result.status, 0, 'SPL_MKIMAGE_SIGN_ARGS value did not get used')
+
+ # Check for evidence of test-mkimage-wrapper class
+ result = runCmd('grep "### uboot-mkimage wrapper message" %s/log.do_uboot_assemble_fitimage' % tempdir, ignore_status=True)
+ self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE did not work')
+ result = runCmd('grep "### uboot-mkimage signing wrapper message" %s/log.do_uboot_assemble_fitimage' % tempdir, ignore_status=True)
+ self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE_SIGN did not work')
+
+ def test_sign_cascaded_uboot_fit_image(self):
+ """
+ Summary: Check if U-Boot FIT image and Image Tree Source (its) are
+ created and signed correctly for the scenario where only
+ both U-Boot proper and Kernel fitImages are being signed.
+ Expected: 1) U-Boot its and FIT image are built successfully
+ 2) Scanning the its file indicates signing is enabled
+ as requested by SPL_SIGN_ENABLE (using keys generated
+ via UBOOT_FIT_GENERATE_KEYS)
+ 3) Dumping the FIT image indicates signature values
+ are present
+ 4) Examination of the do_uboot_assemble_fitimage
+ runfile/logfile indicate that UBOOT_MKIMAGE, UBOOT_MKIMAGE_SIGN
+ and SPL_MKIMAGE_SIGN_ARGS are working as expected.
+ Product: oe-core
+ Author: Klaus Heinrich Kiwi <klaus@linux.vnet.ibm.com> based upon
+ work by Paul Eggleton <paul.eggleton@microsoft.com> and
+ Usama Arif <usama.arif@arm.com>
+ """
+ config = """
+# There's no U-boot deconfig with CONFIG_FIT_SIGNATURE yet, so we need at
+# least CONFIG_SPL_LOAD_FIT and CONFIG_SPL_OF_CONTROL set
+MACHINE = "beaglebone-yocto"
+UBOOT_MACHINE = "am57xx_evm_defconfig"
+SPL_SIGN_ENABLE = "1"
+SPL_SIGN_KEYNAME = "spl-cascaded-oe-selftest"
+SPL_SIGN_KEYDIR = "${TOPDIR}/signing-keys"
+UBOOT_DTB_BINARY = "u-boot.dtb"
+UBOOT_ENTRYPOINT = "0x80000000"
+UBOOT_LOADADDRESS = "0x80000000"
+UBOOT_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000"
+UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart cascaded Kernel comment'"
+UBOOT_DTB_LOADADDRESS = "0x82000000"
+UBOOT_ARCH = "arm"
+SPL_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000"
+SPL_MKIMAGE_SIGN_ARGS = "-c 'a smart cascaded U-Boot comment'"
+UBOOT_EXTLINUX = "0"
+UBOOT_FIT_GENERATE_KEYS = "1"
+UBOOT_FIT_HASH_ALG = "sha256"
+KERNEL_IMAGETYPES += " fitImage "
+KERNEL_CLASSES = " kernel-fitimage test-mkimage-wrapper "
+UBOOT_SIGN_ENABLE = "1"
+FIT_GENERATE_KEYS = "1"
+UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys"
+UBOOT_SIGN_KEYNAME = "kernel-oe-selftest"
+FIT_SIGN_INDIVIDUAL = "1"
+"""
+ self.write_config(config)
+
+ # this scenario exercises a cascading (i.e., Kernel + u-boot)
+ # fitImage sign
+ bitbake("u-boot")
+
+ image_type = "core-image-minimal"
+ deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
+ machine = get_bb_var('MACHINE')
+ fitimage_its_path = os.path.join(deploy_dir_image,
+ "u-boot-its-%s" % (machine,))
+ fitimage_path = os.path.join(deploy_dir_image,
+ "u-boot-fitImage-%s" % (machine,))
+
+ self.assertTrue(os.path.exists(fitimage_its_path),
+ "%s image tree source doesn't exist" % (fitimage_its_path))
+ self.assertTrue(os.path.exists(fitimage_path),
+ "%s FIT image doesn't exist" % (fitimage_path))
+
+ req_itspaths = [
+ ['/', 'images', 'uboot'],
+ ['/', 'images', 'uboot', 'signature'],
+ ['/', 'images', 'fdt'],
+ ['/', 'images', 'fdt', 'signature'],
+ ]
+
+ itspath = []
+ itspaths = []
+ linect = 0
+ sigs = {}
+ with open(fitimage_its_path) as its_file:
+ linect += 1
+ for line in its_file:
+ line = line.strip()
+ if line.endswith('};'):
+ itspath.pop()
+ elif line.endswith('{'):
+ itspath.append(line[:-1].strip())
+ itspaths.append(itspath[:])
+ elif itspath and itspath[-1] == 'signature':
+ itsdotpath = '.'.join(itspath)
+ if not itsdotpath in sigs:
+ sigs[itsdotpath] = {}
+ if not '=' in line or not line.endswith(';'):
+ self.fail('Unexpected formatting in %s sigs section line %d:%s' % (fitimage_its_path, linect, line))
+ key, value = line.split('=', 1)
+ sigs[itsdotpath][key.rstrip()] = value.lstrip().rstrip(';')
+
+ for reqpath in req_itspaths:
+ if not reqpath in itspaths:
+ self.fail('Missing section in its file: %s' % reqpath)
+
+ reqsigvalues_image = {
+ 'algo': '"sha256,rsa2048"',
+ 'key-name-hint': '"spl-cascaded-oe-selftest"',
+ }
+
+ for itspath, values in sigs.items():
+ reqsigvalues = reqsigvalues_image
+ for reqkey, reqvalue in reqsigvalues.items():
+ value = values.get(reqkey, None)
+ if value is None:
+ self.fail('Missing key "%s" in its file signature section %s' % (reqkey, itspath))
+ self.assertEqual(value, reqvalue)
+
+ # Dump the image to see if it really got signed
+ bitbake("u-boot-tools-native -c addto_recipe_sysroot")
+ result = runCmd('bitbake -e u-boot-tools-native | grep ^RECIPE_SYSROOT_NATIVE=')
+ recipe_sysroot_native = result.output.split('=')[1].strip('"')
+ dumpimage_path = os.path.join(recipe_sysroot_native, 'usr', 'bin', 'dumpimage')
+ result = runCmd('%s -l %s' % (dumpimage_path, fitimage_path))
+ in_signed = None
+ signed_sections = {}
+ for line in result.output.splitlines():
+ if line.startswith((' Image')):
+ in_signed = re.search('\((.*)\)', line).groups()[0]
+ elif re.match(' \w', line):
+ in_signed = None
+ elif in_signed:
+ if not in_signed in signed_sections:
+ signed_sections[in_signed] = {}
+ key, value = line.split(':', 1)
+ signed_sections[in_signed][key.strip()] = value.strip()
+ self.assertIn('uboot', signed_sections)
+ self.assertIn('fdt', signed_sections)
+ for signed_section, values in signed_sections.items():
+ value = values.get('Sign algo', None)
+ self.assertEqual(value, 'sha256,rsa2048:spl-cascaded-oe-selftest', 'Signature algorithm for %s not expected value' % signed_section)
+ value = values.get('Sign value', None)
+ self.assertEqual(len(value), 512, 'Signature value for section %s not expected length' % signed_section)
+
+ # Check for SPL_MKIMAGE_SIGN_ARGS
+ result = runCmd('bitbake -e virtual/kernel | grep ^T=')
+ tempdir = result.output.split('=', 1)[1].strip().strip('')
+ result = runCmd('grep "a smart cascaded U-Boot comment" %s/run.do_uboot_assemble_fitimage' % tempdir, ignore_status=True)
+ self.assertEqual(result.status, 0, 'SPL_MKIMAGE_SIGN_ARGS value did not get used')
+
+ # Check for evidence of test-mkimage-wrapper class
+ result = runCmd('grep "### uboot-mkimage wrapper message" %s/log.do_uboot_assemble_fitimage' % tempdir, ignore_status=True)
+ self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE did not work')
+ result = runCmd('grep "### uboot-mkimage signing wrapper message" %s/log.do_uboot_assemble_fitimage' % tempdir, ignore_status=True)
+ self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE_SIGN did not work')
+
+
+
def test_initramfs_bundle(self):
"""
Summary: Verifies the content of the initramfs bundle node in the FIT Image Tree Source (its)
--
2.25.1
prev parent reply other threads:[~2021-03-15 17:01 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-15 16:58 [PATCH 0/4] u-boot: Support for SPL verified boot Klaus Heinrich Kiwi
2021-03-15 16:58 ` [PATCH 1/4] u-boot: Move definitions to common locations Klaus Heinrich Kiwi
2021-03-15 16:58 ` [PATCH 2/4] u-boot: Add infrastructure to SPL verified boot Klaus Heinrich Kiwi
2021-03-15 16:58 ` [PATCH 3/4] u-boot: Use a different Key for SPL signing Klaus Heinrich Kiwi
2021-03-15 16:58 ` Klaus Heinrich Kiwi [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210315165806.1633-5-klaus@linux.vnet.ibm.com \
--to=klaus@linux.vnet.ibm.com \
--cc=andrew@aj.id.au \
--cc=openbmc@lists.ozlabs.org \
--cc=openembedded-core@lists.openembedded.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).