Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tests/nested/manual/hybrid-fde-dbx: hybrid with DBX updates #15080

Merged
merged 1 commit into from
Feb 17, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 150 additions & 0 deletions tests/nested/manual/hybrid-fde-dbx/task.yaml
Original file line number Diff line number Diff line change
@@ -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"
Loading