From 208ba34a43c5372131406329bccf026abef026ed Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Fri, 8 Aug 2025 22:59:45 +0100 Subject: [PATCH] test: add coverage for kernel keyring in TEST-50-DISSECT Use the kernel keyring to verify images in the dissect test. The userspace keyring is still covered by the DDI and mountfsd tests. --- mkosi/mkosi.finalize | 3 + .../TEST-50-DISSECT/meson.build | 1 + test/units/TEST-50-DISSECT.dissect.sh | 20 ++++++ test/units/TEST-50-DISSECT.sh | 62 ++++++------------- 4 files changed, 43 insertions(+), 43 deletions(-) diff --git a/mkosi/mkosi.finalize b/mkosi/mkosi.finalize index bb7ad2d9ea7..99c9d7c7620 100755 --- a/mkosi/mkosi.finalize +++ b/mkosi/mkosi.finalize @@ -13,3 +13,6 @@ if [ -n "$EFI_ARCHITECTURE" ]; then --secureboot-certificate "$SRCDIR/mkosi/mkosi.crt" \ --secureboot-private-key "$SRCDIR/mkosi/mkosi.key" fi + +# Used to sign artifacts verified by kernel platform keyring +cp "$SRCDIR/mkosi/mkosi.crt" "$SRCDIR/mkosi/mkosi.key" "$BUILDROOT/usr/share/" diff --git a/test/integration-tests/TEST-50-DISSECT/meson.build b/test/integration-tests/TEST-50-DISSECT/meson.build index 77370ce4588..d7634debca3 100644 --- a/test/integration-tests/TEST-50-DISSECT/meson.build +++ b/test/integration-tests/TEST-50-DISSECT/meson.build @@ -4,5 +4,6 @@ integration_tests += [ integration_test_template + { 'name' : fs.name(meson.current_source_dir()), 'vm' : true, + 'firmware' : 'auto', }, ] diff --git a/test/units/TEST-50-DISSECT.dissect.sh b/test/units/TEST-50-DISSECT.dissect.sh index a5dc65e4694..b38228792b6 100755 --- a/test/units/TEST-50-DISSECT.dissect.sh +++ b/test/units/TEST-50-DISSECT.dissect.sh @@ -9,6 +9,18 @@ set -o pipefail # shellcheck source=test/units/util.sh . "$(dirname "$0")"/util.sh +# Requires kernel built with certain kconfigs, as listed in README: +# https://oracle.github.io/kconfigs/?config=UTS_RELEASE&config=DM_VERITY_VERIFY_ROOTHASH_SIG&config=DM_VERITY_VERIFY_ROOTHASH_SIG_SECONDARY_KEYRING&config=DM_VERITY_VERIFY_ROOTHASH_SIG_PLATFORM_KEYRING&config=IMA_ARCH_POLICY&config=INTEGRITY_MACHINE_KEYRING +if grep -q "$(openssl x509 -noout -subject -in /usr/share/mkosi.crt | sed 's/^.*CN=//')" /proc/keys && \ + ( . /etc/os-release; [ "$ID" != "centos" ] || systemd-analyze compare-versions "$VERSION_ID" ge 10 ) && \ + ( . /etc/os-release; [ "$ID" != "debian" ] || systemd-analyze compare-versions "$VERSION_ID" ge 13 ) && \ + ( . /etc/os-release; [ "$ID" != "ubuntu" ] || systemd-analyze compare-versions "$VERSION_ID" ge 24.04 ) && \ + systemd-analyze compare-versions "$(cryptsetup --version | sed 's/^cryptsetup \([0-9]*\.[0-9]*\.[0-9]*\) .*/\1/')" ge 2.3.0; then + verity_sig_supported=1 +else + verity_sig_supported=0 +fi + systemd-dissect --json=short "$MINIMAL_IMAGE.raw" | \ grep -q -F '{"rw":"ro","designator":"root","partition_uuid":null,"partition_label":null,"fstype":"squashfs","architecture":null,"verity":"external"' systemd-dissect "$MINIMAL_IMAGE.raw" | grep -q -F "MARKER=1" @@ -71,6 +83,10 @@ if [[ "$verity_count" -lt 1 ]]; then echo "Verity device $MINIMAL_IMAGE.raw not found in /dev/mapper/" exit 1 fi +# Ensure the kernel is verifying the signature if the mkosi key is in the keyring +if [ "$verity_sig_supported" -eq 1 ]; then + veritysetup status "$(cat "$MINIMAL_IMAGE.roothash")-verity" | grep -q "verified (with signature)" +fi systemd-dissect --umount "$IMAGE_DIR/mount" systemd-dissect --umount "$IMAGE_DIR/mount2" @@ -729,6 +745,10 @@ ExecStart=bash -x -c ' \ EOF systemctl start testservice-50k.service systemctl is-active testservice-50k.service +# Ensure the kernel is verifying the signature if the mkosi key is in the keyring +if [ "$verity_sig_supported" -eq 1 ]; then + veritysetup status "$(cat "$MINIMAL_IMAGE.roothash")-verity" | grep -q "verified (with signature)" +fi # First reload should pick up the v1 marker mksquashfs "$VDIR/${VBASE}_1" "$VDIR2/${VBASE}_1.raw" systemctl reload testservice-50k.service diff --git a/test/units/TEST-50-DISSECT.sh b/test/units/TEST-50-DISSECT.sh index 38bafa545fc..0efea0fc180 100755 --- a/test/units/TEST-50-DISSECT.sh +++ b/test/units/TEST-50-DISSECT.sh @@ -110,17 +110,9 @@ install_extension_images OS_RELEASE="$(test -e /etc/os-release && echo /etc/os-release || echo /usr/lib/os-release)" -if systemctl --version | grep -q -- +OPENSSL ; then - # The openssl binary is installed conditionally. If we have OpenSSL support enabled and openssl is - # missing, fail early with a proper error message. - if ! command -v openssl &>/dev/null; then - echo "openssl binary is missing" >/failed - exit 1 - fi - - OPENSSL_CONFIG="$(mktemp)" - # Unfortunately OpenSSL insists on reading some config file, hence provide one with mostly placeholder contents - cat >"${OPENSSL_CONFIG:?}" <"${OPENSSL_CONFIG:?}" <"$MINIMAL_IMAGE.verity-sig" - # Pad it - truncate -s "$signature_size" "$MINIMAL_IMAGE.verity-sig" - # Register certificate in the (userspace) verity key ring - mkdir -p /run/verity.d - ln -s "$MINIMAL_IMAGE.crt" /run/verity.d/ok.crt -fi +# Sign Verity root hash with mkosi key +openssl smime -sign -nocerts -noattr -binary \ + -in "$MINIMAL_IMAGE.roothash" \ + -inkey /usr/share/mkosi.key \ + -signer /usr/share/mkosi.crt \ + -outform der \ + -out "$MINIMAL_IMAGE.roothash.p7s" +# Generate signature partition JSON data +echo '{"rootHash":"'"$MINIMAL_IMAGE_ROOTHASH"'","signature":"'"$(base64 -w 0 <"$MINIMAL_IMAGE.roothash.p7s")"'"}' >"$MINIMAL_IMAGE.verity-sig" +# Pad it +truncate -s "$signature_size" "$MINIMAL_IMAGE.verity-sig" # Construct a UUID from hash # input: 11111111222233334444555566667777 @@ -181,30 +164,23 @@ uuid="$(head -c 32 "$MINIMAL_IMAGE.roothash" | sed -r 's/(.{8})(.{4})(.{4})(.{4} echo -e "label: gpt\nsize=$root_size, type=$ROOT_GUID, uuid=$uuid" | sfdisk "$MINIMAL_IMAGE.gpt" uuid="$(tail -c 32 "$MINIMAL_IMAGE.roothash" | sed -r 's/(.{8})(.{4})(.{4})(.{4})(.+)/\1-\2-\3-\4-\5/')" echo -e "size=$verity_size, type=$VERITY_GUID, uuid=$uuid" | sfdisk "$MINIMAL_IMAGE.gpt" --append -if [[ -n "${OPENSSL_CONFIG:-}" ]]; then - echo -e "size=$signature_size, type=$SIGNATURE_GUID" | sfdisk "$MINIMAL_IMAGE.gpt" --append -fi +echo -e "size=$signature_size, type=$SIGNATURE_GUID" | sfdisk "$MINIMAL_IMAGE.gpt" --append + sfdisk --part-label "$MINIMAL_IMAGE.gpt" 1 "Root Partition" sfdisk --part-label "$MINIMAL_IMAGE.gpt" 2 "Verity Partition" -if [[ -n "${OPENSSL_CONFIG:-}" ]]; then - sfdisk --part-label "$MINIMAL_IMAGE.gpt" 3 "Signature Partition" -fi +sfdisk --part-label "$MINIMAL_IMAGE.gpt" 3 "Signature Partition" loop="$(losetup --show -P -f "$MINIMAL_IMAGE.gpt")" partitions=( "${loop:?}p1" "${loop:?}p2" + "${loop:?}p3" ) -if [[ -n "${OPENSSL_CONFIG:-}" ]]; then - partitions+=("${loop:?}p3") -fi # The kernel sometimes(?) does not emit "add" uevent for loop block partition devices. # Let's not expect the devices to be initialized. udevadm wait --timeout=60 --settle --initialized=no "${partitions[@]}" udevadm lock --timeout=60 --device="${loop}p1" dd if="$MINIMAL_IMAGE.raw" of="${loop}p1" udevadm lock --timeout=60 --device="${loop}p2" dd if="$MINIMAL_IMAGE.verity" of="${loop}p2" -if [[ -n "${OPENSSL_CONFIG:-}" ]]; then - udevadm lock --timeout=60 --device="${loop}p3" dd if="$MINIMAL_IMAGE.verity-sig" of="${loop}p3" -fi +udevadm lock --timeout=60 --device="${loop}p3" dd if="$MINIMAL_IMAGE.verity-sig" of="${loop}p3" losetup -d "$loop" udevadm settle --timeout=60