From 6e1b31aa90e75a0c0b8814d7f840f48ebc3e625e Mon Sep 17 00:00:00 2001 From: Maciej Borzecki Date: Fri, 14 Feb 2025 12:46:46 +0100 Subject: [PATCH] tests/nested/manual/hybrid-fde-dbx: hybrid with DBX updates Spread test for a hybrid system and a DBX update Signed-off-by: Maciej Borzecki --- tests/nested/manual/hybrid-fde-dbx/task.yaml | 150 +++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 tests/nested/manual/hybrid-fde-dbx/task.yaml diff --git a/tests/nested/manual/hybrid-fde-dbx/task.yaml b/tests/nested/manual/hybrid-fde-dbx/task.yaml new file mode 100644 index 00000000000..067372fadf7 --- /dev/null +++ b/tests/nested/manual/hybrid-fde-dbx/task.yaml @@ -0,0 +1,150 @@ +summary: Verify DBX on a hybrid system + +details: | + Verify handling of DBX updates on a hybrid system. + +systems: [-ubuntu-1*, -ubuntu-20*] + +environment: + NESTED_ENABLE_TPM: true + NESTED_ENABLE_SECURE_BOOT: true + NESTED_BUILD_SNAPD_FROM_CURRENT: true + NESTED_REPACK_KERNEL_SNAP: true + NESTED_ENABLE_OVMF: true + # store related setup + STORE_ADDR: localhost:11028 + STORE_DIR: $(pwd)/fake-store-blobdir + +prepare: | + # shellcheck source=tests/lib/prepare.sh + . "$TESTSLIB/prepare.sh" + #shellcheck source=tests/lib/nested.sh + . "$TESTSLIB"/nested.sh + + tests.pkgs install efitools + + if [ "$TRUST_TEST_KEYS" = "false" ]; then + echo "This test needs test keys to be trusted" + exit + fi + + "$TESTSTOOLS"/store-state setup-fake-store "$STORE_DIR" + + echo "Expose the needed assertions through the fakestore" + cp "$TESTSLIB"/assertions/developer1.account "$STORE_DIR/asserts" + cp "$TESTSLIB"/assertions/developer1.account-key "$STORE_DIR/asserts" + cp "$TESTSLIB"/assertions/testrootorg-store.account-key "$STORE_DIR/asserts" + export SNAPPY_FORCE_SAS_URL=http://$STORE_ADDR + + version="$(nested_get_version)" + + # Retrieve the gadget + snap download --basename=pc --channel="$version/edge" pc + # the fakestore needs the assertion + snap ack pc.assert + # keep original blob just so we can find the assertion later + cp pc.snap pc.snap.orig + + # New modified gadget + unsquashfs -d pc-gadget pc.snap + echo 'console=ttyS0 systemd.journald.forward_to_console=1' > pc-gadget/cmdline.extra + + echo "Sign the shim binary" + KEY_NAME=$(tests.nested download snakeoil-key) + SNAKEOIL_KEY="$PWD/$KEY_NAME.key" + SNAKEOIL_CERT="$PWD/$KEY_NAME.pem" + tests.nested secboot-sign gadget pc-gadget "$SNAKEOIL_KEY" "$SNAKEOIL_CERT" + snap pack --filename=pc.snap pc-gadget/ + + # Retrieve kernel + snap download --basename=pc-kernel-from-store --channel="$version/edge" pc-kernel + # the fakestore needs this assertion + snap ack pc-kernel-from-store.assert + # Build kernel with initramfs with the compiled snap-bootstrap + if os.query is-ubuntu-ge 24.04; then + uc24_build_initramfs_kernel_snap "$PWD/pc-kernel-from-store.snap" "$NESTED_ASSETS_DIR" + else + uc20_build_initramfs_kernel_snap "$PWD/pc-kernel-from-store.snap" "$NESTED_ASSETS_DIR" + fi + mv "${NESTED_ASSETS_DIR}"/pc-kernel_*.snap pc-kernel-repacked.snap + + gendeveloper1 sign-model < "$TESTSLIB"/assertions/developer1-"$version"-classic-dangerous.json > classic.model + + # setup_nested_hybrid_system.sh runs the muinstaller to install a hybrid + # system + # shellcheck disable=SC2086 + "${TESTSTOOLS}"/setup_nested_hybrid_system.sh \ + --model classic.model \ + --store-dir "${STORE_DIR}" \ + --gadget pc.snap \ + --gadget-assertion pc.assert \ + --kernel pc-kernel-repacked.snap \ + --kernel-assertion pc-kernel-from-store.assert + + # basic things look fine + remote.exec "cat /etc/os-release" | MATCH 'NAME="Ubuntu"' + remote.exec "snap changes" | MATCH "Done.* Initialize system state" + remote.exec "snap list" | MATCH pc-kernel + + remote.exec "sudo test -d /var/lib/snapd/device/fde" + remote.exec "sudo test -e /var/lib/snapd/device/fde/marker" + + keys_dir="$(tests.nested get assets-path)/ovmf/secboot/" + # generate 3 dbx updates + MYGUID="11111111-0000-1111-0000-000000000000" + # generate a key + openssl req -new -x509 -newkey rsa:2048 -subj "/CN=bad key/" \ + -keyout "bad-key.key" -out "bad-key.crt" -days 3650 -nodes -sha256 + # convert to EFI sig list + cert-to-efi-sig-list -g $MYGUID "bad-key.crt" "bad-key.esl" + # and sign as an update for appending + sign-efi-sig-list -a -c "$keys_dir/KEK.crt" -k "$keys_dir/KEK.key" dbx \ + "bad-key.esl" "dbx-update.auth" + + remote.push dbx-update.auth + remote.exec sudo apt install efitools -y + +restore: | + "$TESTSTOOLS"/store-state teardown-fake-store "$STORE_DIR" + +execute: | + echo "Perform DBX update and verify that the system boots correctly" + + update_payload="$(base64 -w0 dbx-update.auth)" + echo "{\"action\":\"efi-secureboot-update-db-prepare\",\"key-database\":\"DBX\",\"payload\":\"$update_payload\"}" | \ + remote.exec "sudo snap debug api -X POST -H 'Content-Type: application/json' /v2/system-secureboot" > prepare.out + jq -r .status < prepare.out | MATCH "OK" + remote.exec snap change --last=fde-efi-secureboot-db-update | \ + MATCH 'Done .* Prepare for external EFI DBX update' + remote.exec snap change --last=fde-efi-secureboot-db-update | \ + MATCH 'Do .* Reseal after external EFI DBX update' + + remote.exec sudo efi-readvar -v dbx 2>&1 | tee efi-dbx-state-initial.log + # count how many entries we have in DBX initially + initial_dbx_entries_count="$(grep -c 'List ' efi-dbx-state-initial.log)" + + remote.exec sudo efi-readvar 2>&1 | tee efi-vars.log + remote.push dbx-update.auth + remote.exec "sudo chattr -i /sys/firmware/efi/efivars/dbx-*" + # update dbx + remote.exec sudo efi-readvar -v dbx 2>&1 | tee efi-dbx-before.log + # expecting no additional entries in the list + grep -c 'List ' efi-dbx-before.log | MATCH "$initial_dbx_entries_count" + remote.exec sudo efi-updatevar -a -f dbx-update.auth dbx + remote.exec sudo efi-readvar -v dbx 2>&1 | tee efi-dbx-after.log + # expecting one additional entry in the list + grep -c 'List ' efi-dbx-after.log | MATCH "$((initial_dbx_entries_count + 1))" + + echo "Completed with a 'cleanup request'" + echo '{"action":"efi-secureboot-update-db-cleanup"}' | \ + remote.exec "sudo snap debug api -X POST -H 'Content-Type: application/json' /v2/system-secureboot" > cleanup.out + jq -r .status < prepare.out | MATCH "OK" + remote.exec snap change --last=fde-efi-secureboot-db-update | MATCH 'Done .* Reseal after external EFI DBX update' + + echo "The system reboots without problems" + boot_id="$( tests.nested boot-id )" + remote.exec "sudo reboot" || true + remote.wait-for reboot "${boot_id}" + + # the system should come up + remote.exec "snap list"