From patchwork Mon Mar 10 09:35:49 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Freihofer X-Patchwork-Id: 58543 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1952EC282DE for ; Mon, 10 Mar 2025 09:37:16 +0000 (UTC) Received: from mail-wr1-f43.google.com (mail-wr1-f43.google.com [209.85.221.43]) by mx.groups.io with SMTP id smtpd.web10.33762.1741599425843135804 for ; Mon, 10 Mar 2025 02:37:06 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=Jqok57Ld; spf=pass (domain: gmail.com, ip: 209.85.221.43, mailfrom: adrian.freihofer@gmail.com) Received: by mail-wr1-f43.google.com with SMTP id ffacd0b85a97d-3913d129c1aso987487f8f.0 for ; Mon, 10 Mar 2025 02:37:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741599424; x=1742204224; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Ag88PIB5bnXRAaSn0yh8boc2KFmajBDjctdhyev27H4=; b=Jqok57LdFnenTvUPKG/ONJmYJQkbnPMphMW7cmLMKTWmx5izutxQVmSfXrV6YqEIbW orRglyqeQuO+9lApOYZDaa4KjVQNbKZK0gwNbNrkQHHvpxRR9xUJjM9yu8PTkbCHwbGv 2lZJYkwIbcyAThwq1F5uTlwew8gpOMGSDnzvR26Y9smLO8l2hklEl1WBXROEDtcvfpNw Gl9iFD+d9wNDaiMtoFo0P+FkMU7UuiDOtr/yf8/SIqdBgoW9ACcMichctoIR/Z+FLOTD J0dC4EbOYoCH7gTPvDQZXSeyXwdCV0zc+g55Uv4uUOlgsQpzMECWF0aGLVSKeDY+pwXP pd5Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741599424; x=1742204224; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Ag88PIB5bnXRAaSn0yh8boc2KFmajBDjctdhyev27H4=; b=RqoOLbmKbvl9sn903HgMdzl7YDOR0r7p0moZEAJwwFwpmZAeGkBc/0n6hthgsIADMD K+QVpVaTn61QDyy600H6aM9RY3JjLwzfsdZvVfzDOcLmjIIoL1D9R22LHYksfralpaTD F1YQKXzUBdzGUDt7Q0AoEGr4kxi1xBuXcti7C/X377azWI1wAcjiGtA4iFBbdBIUinO0 mzri1/0jc/EBv5GjFgoNhVrxjr0etLPWdKAzwel86c87RQq1crV7J5ET2phYhOvxW2iV 4X8Z5EJIZTwdJR6hfr1I/+90P/e9t1XW1eZwzE6Q2dhqT+JbK+x/E/qwTqTKP9F28Ubj IcuQ== X-Gm-Message-State: AOJu0Yy7IIM74v32Ggb03Kb+Lw9n7Uwat+nIK8hUvL2nQe6qBuiDDB7f D69fONQmkszByQybOgvfRyr1kvBmew/OgP00q0Wg9HIvXt9J1Ps/6hSeQg== X-Gm-Gg: ASbGncv4Z9r/YGZuaMWs5UNVTIkCyC/sj0jTanAAPSDzw0am5FBa+nGJWV/Hi1iQEQz kxQ1uFJIPsUIbGvk6NoObPYWevVTYbr9X7KmXlzhSb+bkY2QWr+q4zqib2pT5Y/zZSzgyFgwRIN 995z/yAkxUiEfn6yCo6+tQ/kaxJHrpO06LvKTPUy6eCuqo2nKAHThKhH/5QJe8ehpO/FZPdE9Px fv3Ib81QN2g92mEYSJienlbWzmVo+jCSsE1bwK61su8V8WDiMUdUMtBFe53EbEG0iZj7Bzpnojq cJd98WYBiXRZmEmREhw/KWB3NiIDlVhWu/iJFur0Px1d9i+31Gjmbh2JubCWNsdlvLY= X-Google-Smtp-Source: AGHT+IFOleMv8DrxwhYdITWB+04vfCdoKxd65BxA1E1JUQd2zZtmJ6wVfW/OO9E1buAO6FSoMGEbSQ== X-Received: by 2002:a05:6000:184b:b0:38f:23c4:208c with SMTP id ffacd0b85a97d-3913af2e472mr4961017f8f.18.1741599423958; Mon, 10 Mar 2025 02:37:03 -0700 (PDT) Received: from wsadrian16.fritz.box ([2a02:169:59a6:0:55c4:f628:91f3:4287]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3912bfb79fbsm14554454f8f.13.2025.03.10.02.37.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Mar 2025 02:37:03 -0700 (PDT) From: Adrian Freihofer X-Google-Original-From: Adrian Freihofer To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer Subject: [PATCH 7/7] oe-selftest: fitimage add more kernel tests Date: Mon, 10 Mar 2025 10:35:49 +0100 Message-ID: <20250310093641.1983560-8-adrian.freihofer@siemens.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250310093641.1983560-1-adrian.freihofer@siemens.com> References: <20250310093641.1983560-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Mon, 10 Mar 2025 09:37:16 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/212502 * 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 --- 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 - def test_initramfs_bundle(self): + 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_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.