From 0a5b65b83dcd9f8d1d22d074fdfad1f1e472827c Mon Sep 17 00:00:00 2001 From: Adrian Freihofer Date: Mon, 10 Mar 2025 10:35:49 +0100 Subject: [PATCH] oe-selftest: fitimage add more kernel tests * Test with only one externally provided ssh key not only with two keys generated by the kernel-fitimage.bbclass itself. * Add a test which signs only the configuration but not the image nodes. There was no test case which covered the probably much more important use case of setting FIT_SIGN_INDIVIDUAL = "0". * Cover also the unbundled initramfs use case. Also this use case is probably much more relevant than the bundled initramnfs use case. Signed-off-by: Adrian Freihofer Signed-off-by: Richard Purdie --- meta/lib/oeqa/selftest/cases/fitimage.py | 151 ++++++++++++++++++++++- 1 file changed, 149 insertions(+), 2 deletions(-) diff --git a/meta/lib/oeqa/selftest/cases/fitimage.py b/meta/lib/oeqa/selftest/cases/fitimage.py index 6f3bf296d56..721628d8e73 100644 --- a/meta/lib/oeqa/selftest/cases/fitimage.py +++ b/meta/lib/oeqa/selftest/cases/fitimage.py @@ -39,6 +39,52 @@ class FitImageTestCase(OESelftestTestCase): MKIMAGE_HASH_LENGTHS = { 'sha256': 64, 'sha384': 96, 'sha512': 128 } MKIMAGE_SIGNATURE_LENGTHS = { 'rsa2048': 512 } + def _gen_signing_key(self, bb_vars): + """Generate a key pair and a singing certificate + + Generate a UBOOT_SIGN_KEYNAME in the UBOOT_SIGN_KEYDIR similar to what + the FIT_GENERATE_KEYS feature does. However, having a static key is + probably a more realistic use case than generating a random key with + each clean build. So this needs to be tested as well. + The FIT_GENERATE_KEYS generates 2 keys: The UBOOT_SIGN_KEYNAME and the + UBOOT_SIGN_IMG_KEYNAME. The UBOOT_SIGN_IMG_KEYNAME is used by the + FIT_SIGN_INDIVIDUAL feature only. Testing if everything is working if + there is only one key available is important as well. Therefore this + function generates only the keys which are really needed, not just two. + """ + + # Define some variables which are usually defined by the kernel-fitimage.bbclass. + # But for testing purpose check if the uboot-sign.bbclass is independent from + # the kernel-fitimage.bbclass + fit_sign_numbits = bb_vars['FIT_SIGN_NUMBITS'] or "2048" + fit_key_genrsa_args = bb_vars['FIT_KEY_GENRSA_ARGS'] or "-F4" + fit_key_req_args = bb_vars['FIT_KEY_REQ_ARGS'] or "-batch -new" + fit_key_sign_pkcs = bb_vars['FIT_KEY_SIGN_PKCS'] or "-x509" + + uboot_sign_keydir = bb_vars['UBOOT_SIGN_KEYDIR'] + sign_keys = [bb_vars['UBOOT_SIGN_KEYNAME']] + if bb_vars['FIT_SIGN_INDIVIDUAL'] == "1": + sign_keys.append(bb_vars['UBOOT_SIGN_IMG_KEYNAME']) + for sign_key in sign_keys: + sing_key_path = os.path.join(uboot_sign_keydir, sign_key) + if not os.path.isdir(uboot_sign_keydir): + os.makedirs(uboot_sign_keydir) + openssl_bindir = FitImageTestCase._setup_native('openssl-native') + openssl_path = os.path.join(openssl_bindir, 'openssl') + runCmd("%s genrsa %s -out %s.key %s" % ( + openssl_path, + fit_key_genrsa_args, + sing_key_path, + fit_sign_numbits + )) + runCmd("%s req %s %s -key %s.key -out %s.crt" % ( + openssl_path, + fit_key_req_args, + fit_key_sign_pkcs, + sing_key_path, + sing_key_path + )) + @staticmethod def _gen_random_file(file_path, num_bytes=65536): with open(file_path, 'wb') as file_out: @@ -632,7 +678,50 @@ FIT_DESC = "A model description" self._test_fitimage(bb_vars) - def test_sign_fit_image(self): + def test_sign_fit_image_configurations(self): + """ + Summary: Check if FIT image and Image Tree Source (its) are created + and the configuration nodes are signed correctly. + Expected: 1) its and FIT image are built successfully + 2) Scanning the its file indicates signing is enabled + as requested by UBOOT_SIGN_ENABLE (using 1 key + generated by the test not via FIT_GENERATE_KEYS) + 3) Dumping the FIT image indicates signature values + are present (only for the configuration nodes as + FIT_SIGN_INDIVIDUAL is disabled) + 4) Verify the FIT image contains the comments passed via + UBOOT_MKIMAGE_SIGN_ARGS once per configuration node. + """ + # Generate a configuration section which gets included into the local.conf file + config = """ +# Enable creation of fitImage +MACHINE = "beaglebone-yocto" +KERNEL_IMAGETYPES += " fitImage " +KERNEL_CLASSES = " kernel-fitimage " +UBOOT_SIGN_ENABLE = "1" +UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys" +UBOOT_SIGN_KEYNAME = "dev" +UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'" +""" + config = self._config_add_uboot_env(config) + self.write_config(config) + + # Retrieve some variables from bitbake + bb_vars = self._fit_get_bb_vars([ + 'FIT_KEY_GENRSA_ARGS', + 'FIT_KEY_REQ_ARGS', + 'FIT_KEY_SIGN_PKCS', + 'FIT_SIGN_NUMBITS', + 'UBOOT_SIGN_KEYDIR', + ]) + + # Do not use the random keys generated by FIT_GENERATE_KEYS. + # Using a static key is probably a more realistic scenario. + self._gen_signing_key(bb_vars) + + self._test_fitimage(bb_vars) + + def test_sign_fit_image_individual(self): """ Summary: Check if FIT image and Image Tree Source (its) are created and all nodes are signed correctly. @@ -673,8 +762,66 @@ UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'" bb_vars = self._fit_get_bb_vars() self._test_fitimage(bb_vars) + def test_fit_image_sign_initramfs(self): + """ + Summary: Verifies the content of the initramfs node in the FIT Image Tree Source (its) + The FIT settings are set by the test case. + The machine used is beaglebone-yocto. + Expected: 1. The ITS is generated with initramfs support + 2. All the fields in the kernel node are as expected (matching the + conf settings) + 3. The kernel is included in all the available configurations and + its hash is included in the configuration signature + + Product: oe-core + Author: Abdellatif El Khlifi + """ + + config = """ +DISTRO="poky" +MACHINE = "beaglebone-yocto" +INITRAMFS_IMAGE = "core-image-minimal-initramfs" +INITRAMFS_SCRIPTS = "" +UBOOT_MACHINE = "am335x_evm_defconfig" +KERNEL_CLASSES = " kernel-fitimage " +KERNEL_IMAGETYPES = "fitImage" +UBOOT_SIGN_ENABLE = "1" +UBOOT_SIGN_KEYNAME = "beaglebonekey" +UBOOT_SIGN_KEYDIR ?= "${DEPLOY_DIR_IMAGE}" +UBOOT_DTB_BINARY = "u-boot.dtb" +UBOOT_ENTRYPOINT = "0x80000000" +UBOOT_LOADADDRESS = "0x80000000" +UBOOT_RD_LOADADDRESS = "0x88000000" +UBOOT_RD_ENTRYPOINT = "0x88000000" +UBOOT_DTB_LOADADDRESS = "0x82000000" +UBOOT_ARCH = "arm" +UBOOT_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000" +UBOOT_MKIMAGE_KERNEL_TYPE = "kernel" +UBOOT_EXTLINUX = "0" +FIT_GENERATE_KEYS = "1" +KERNEL_IMAGETYPE_REPLACEMENT = "zImage" +FIT_KERNEL_COMP_ALG = "none" +FIT_HASH_ALG = "sha256" +""" + config = self._config_add_uboot_env(config) + self.write_config(config) + + # Retrieve some variables from bitbake + bb_vars = self._fit_get_bb_vars([ + 'FIT_KEY_GENRSA_ARGS', + 'FIT_KEY_REQ_ARGS', + 'FIT_KEY_SIGN_PKCS', + 'FIT_SIGN_NUMBITS', + 'UBOOT_SIGN_KEYDIR', + ]) + + # Do not use the random keys generated by FIT_GENERATE_KEYS. + # Using a static key is probably a more realistic scenario. + self._gen_signing_key(bb_vars) + + self._test_fitimage(bb_vars) - def test_initramfs_bundle(self): + def test_fit_image_sign_initramfs_bundle(self): """ Summary: Verifies the content of the initramfs bundle node in the FIT Image Tree Source (its) The FIT settings are set by the test case. -- 2.47.3