SecureValueRecovery2/trustedimage/verify_gcpsnp_release.sh
2025-03-20 15:17:46 -07:00

183 lines
5.4 KiB
Bash
Executable File

#!/bin/bash
set -euo pipefail
cd $(dirname $0)/../enclave/releases/gcpsnp
RELEASE=$1
ARCHIVE=$PWD/$RELEASE.tar.gz
EVENTLOG=$PWD/$RELEASE.eventlog
if [ ! -f $ARCHIVE ]; then
echo "Missing $ARCHIVE"
exit 1
fi
if [ ! -f $EVENTLOG ]; then
echo "Missing $EVENTLOG"
exit 1
fi
echo "=== Preparing Disk ==="
DIR="$(mktemp -d)"
echo "Using temporary directory $DIR"
DELETE_DIR=y
function Clean1 {
if [ "${DELETE_DIR,,}" != "n" ]; then
echo "Cleaning up directory $DIR"
rm -rf $DIR
else
echo "Leaving directory $DIR"
fi
}
trap Clean1 EXIT
IMAGE=$DIR/disk.raw
echo "Extracting disk image into $IMAGE"
mkdir -p $DIR
pushd $DIR >/dev/null
tar xzf $ARCHIVE
popd
echo "Finding unused loop device"
LOOP_DEVICE="$(sudo losetup -f)"
echo "Setting up disk loop device $LOOP_DEVICE"
sudo losetup -Pr $LOOP_DEVICE $IMAGE
UMOUNT=y
ROOT=$DIR/root
BOOT=$ROOT/boot
mkdir -p $ROOT
echo "Mounting / at $ROOT and /boot at $BOOT"
sudo mount -o ro ${LOOP_DEVICE}p2 $ROOT
sudo mount -o ro ${LOOP_DEVICE}p1 $BOOT
function Clean2 {
if [ "${UMOUNT,,}" != "n" ]; then
echo "Umounting $BOOT and $ROOT"
sudo umount -l $BOOT
sudo umount -l $ROOT
else
echo "Leaving root directory mounted for further investigation:"
echo " ${LOOP_DEVICE}p2 at $ROOT"
echo " ${LOOP_DEVICE}p1 at $BOOT"
echo "When finished, run:"
echo " sudo umount -l $BOOT"
echo " sudo umount -l $ROOT"
fi
echo "Detaching loop device $LOOP_DEVICE"
sudo losetup -d $LOOP_DEVICE
Clean1
}
trap Clean2 EXIT
echo
echo "=== PCRS: ==="
tpm2_eventlog $EVENTLOG | yq '.pcrs.sha256' | sed 's/0x//'
echo
echo "=== Checking PCR9 file digests ==="
PCR9_FILES=$DIR/pcr9
echo "Extracting file digests into $PCR9_FILES"
tpm2_eventlog $EVENTLOG | \
yq -r '.events[] | select(.PCRIndex == 9) | {"E": .Event.String, "D": .Digests[1].Digest} | .D + " " + .E' | \
sed "s/(.*)//; s# # $BOOT#" | \
tee $PCR9_FILES
echo "Checking PCR9 file digests match"
sha256sum -c $PCR9_FILES
echo
echo "=== Checking PCR8 Verity hash is in kernel commandline and matches ==="
echo "Extracting PCR8 verity hash"
VERITYHASH="$(tpm2_eventlog $EVENTLOG | \
yq -r '.events[] | select(.PCRIndex == 8) | select(.Event.String | test("kernel_cmdline:")) | .Event.String | capture("svr3verity=(?<hash>[^ ]*)") | .hash')"
echo "Verifying dm-verity with root hash $VERITYHASH"
sudo veritysetup verify ${LOOP_DEVICE}p2 ${LOOP_DEVICE}p3 $VERITYHASH
echo "Verity verified"
echo
echo "=== Hashing relevant binaries ==="
function CompareSHA256 {
if [ ! -f "$1" ]; then
echo "$1 not found"
return 1
fi
local sha1=$(sha256sum "$1" | awk '{ print $1 }')
local sha2=$(sha256sum "$2" | awk '{ print $1 }')
if [ "$sha1" == "$sha2" ]; then
echo "Checksums match for locally built binary $1 and release disk binary $2"
return 0
else
echo "Checksum verification FAILED"
echo "Locally built binary $1 has checksum $sha1"
echo "Release disk binary $2 has checksum $sha2"
return 1
fi
}
pushd "../../../trustedimage/debian2"
CompareSHA256 "initramfs_hook.sh" "$ROOT/etc/initramfs-tools/hooks/initramfs_hook.sh"
CompareSHA256 "initramfs_local-top.sh" "$ROOT/etc/initramfs-tools/scripts/local-top/initramfs_local-top.sh"
CompareSHA256 "initramfs_local-bottom.sh" "$ROOT/etc/initramfs-tools/scripts/local-bottom/initramfs_local-bottom.sh"
CompareSHA256 "svr3" "$ROOT/usr/bin/svr3"
popd
pushd ../../.. >/dev/null
CompareSHA256 "enclave/build/enclave.gcpsnp" "$ROOT/usr/bin/enclave.gcpsnp"
CompareSHA256 "enclave/build/enclave.azuresnp" "$ROOT/usr/bin/enclave.azuresnp"
CompareSHA256 "host/cmd/svr3gcp/svr3gcp" "$ROOT/usr/bin/svr3gcp"
popd >/dev/null
echo
echo "=== Diff ==="
LOCAL_IMAGE="$(realpath ../../../trustedimage/build/debian2.out/disk.raw-1)"
if [ ! -f $LOCAL_IMAGE ]; then
echo "No local image at $LOCAL_IMAGE, skipping diff"
echo "Generate image by running 'make build/debian2.out' in the trustedimage/ directory"
else
echo "Finding unused loop device"
LOOP2_DEVICE="$(sudo losetup -f)"
echo "Setting up disk loop device $LOOP2_DEVICE"
sudo losetup -Pr $LOOP2_DEVICE $LOCAL_IMAGE
mkdir -p $DIR/local
echo "Mounting locally-generated drive to $DIR/local"
sudo mount ${LOOP2_DEVICE}p2 $DIR/local
sudo mount ${LOOP2_DEVICE}p1 $DIR/local/boot
function Clean3 {
if [ "${UMOUNT,,}" != "n" ]; then
echo "Umounting /local"
sudo umount -l $DIR/local/boot
sudo umount -l $DIR/local
else
echo "Leaving local directory mounted for further investigation:"
echo " ${LOOP2_DEVICE}p2 at $DIR/local"
echo " ${LOOP2_DEVICE}p1 at $DIR/local/boot"
echo "When finished, run:"
echo " sudo umount -l $DIR/local"
echo " sudo umount -l $DIR/local/boot"
fi
echo "Detaching loop device $LOOP2_DEVICE"
sudo losetup -d $LOOP2_DEVICE
Clean2
}
trap Clean3 EXIT
echo "Running diff against locally generated drive (local/) and release root drive (root/)"
pushd $DIR >/dev/null
sudo diff --brief --recursive --no-dereference local/ root/ && echo "*** No differences found ***" || echo "^^^ Differences ^^^"
popd
fi
echo
echo "=== Complete ==="
if [ "${DELETE_DIR,,}" == "y" ]; then
echo -n "Delete temporary directory $DIR (including disk image)? [Y/n]: "
read DELETE_DIR
fi
if [ "${DELETE_DIR,,}" == "n" ]; then
echo -n "Umount filesystems mounted under $DIR? [Y/n]: "
read UMOUNT
fi