#!/usr/bin/env bash
# Verify, from inside an AMD SEV-SNP CVM, that the launch measurement signed
# by the AMD-SP matches an independently computed measurement over the OVMF
# firmware, kernel, initrd, and kernel command line.
#
# Flow:
#   1. snpguest report ........... fetch the attestation report from /dev/sev-guest
#   2. snpguest display .......... extract the Measurement field (48-byte SHA-384)
#   3. sev-snp-measure ........... compute the expected measurement from local artefacts
#   4. compare hex strings ....... MATCH means the running CVM was launched
#                                  from exactly these OVMF/kernel/initrd/cmdline
#
# Override any of these via env vars if needed:
OVMF="${OVMF:-/boot/OVMF.amdsev.fd}"
KERNEL="${KERNEL:-/boot/vmlinuz}"
INITRD="${INITRD:-/boot/initrd.img}"
# Reconstruct the -append string QEMU was launched with by reading the
# running kernel's cmdline and stripping the "initrd=initrd " token that
# QEMU prepends when -initrd is used (sev-snp-measure re-adds it itself).
APPEND="${APPEND:-$(sed -e 's/^initrd=initrd //' -e 's/ initrd=initrd / /' /proc/cmdline | tr -d '\n')}"
VCPUS="${VCPUS:-$(nproc)}"
VCPU_FAMILY="${VCPU_FAMILY:-$(awk '/^cpu family/{print $4; exit}' /proc/cpuinfo)}"
VCPU_MODEL="${VCPU_MODEL:-$(awk '/^model[^ ]/{print $3; exit}' /proc/cpuinfo)}"
VCPU_STEPPING="${VCPU_STEPPING:-$(awk '/^stepping/{print $3; exit}' /proc/cpuinfo)}"

set -euo pipefail

WORK=$(mktemp -d); trap "rm -rf '$WORK'" EXIT

# Install snpguest if missing.
if ! command -v snpguest >/dev/null; then
    echo "[+] Installing snpguest..."
    curl -fsSL https://github.com/virtee/snpguest/releases/download/v0.10.0/snpguest \
        -o /usr/local/bin/snpguest
    chmod +x /usr/local/bin/snpguest
fi

# pipx drops its shims in ~/.local/bin, which is not on root's default PATH.
export PATH="$PATH:$HOME/.local/bin"

# Install sev-snp-measure (in an isolated venv via pipx) if missing.
if ! command -v sev-snp-measure >/dev/null; then
    echo "[+] Installing sev-snp-measure via pipx..."
    if ! command -v pipx >/dev/null; then
        apt-get update
        apt-get install -y --no-install-recommends pipx >/dev/null
    fi
    pipx install --quiet sev-snp-measure
fi

echo "[+] Fetching SEV-SNP attestation report..."
snpguest report "$WORK/report.bin" "$WORK/nonce.bin" --random >/dev/null

# Extract the Measurement field from the report (48-byte SHA-384, printed as
# multiple space-separated hex lines by snpguest).
REPORT_MEAS=$(snpguest display report "$WORK/report.bin" \
    | awk '/^Measurement:/{flag=1; next} /^[A-Z][a-z]/{flag=0} flag' \
    | tr -d ' \n')

echo "[+] Computing expected measurement with sev-snp-measure..."
EXPECTED_MEAS=$(sev-snp-measure --mode snp \
    --vcpus "$VCPUS" \
    --vcpu-family "$VCPU_FAMILY" \
    --vcpu-model "$VCPU_MODEL" \
    --vcpu-stepping "$VCPU_STEPPING" \
    --ovmf "$OVMF" \
    --kernel "$KERNEL" \
    --initrd "$INITRD" \
    --append "$APPEND" \
    --output-format hex)
EXPECTED_MEAS="${EXPECTED_MEAS^^}"

echo
echo "OVMF     : $OVMF"
echo "Kernel   : $KERNEL"
echo "Initrd   : $INITRD"
echo "Cmdline  : $APPEND"
echo "vCPUs    : $VCPUS (family=$VCPU_FAMILY model=$VCPU_MODEL stepping=$VCPU_STEPPING)"
echo
echo "Report measurement   : $REPORT_MEAS"
echo "Expected measurement : $EXPECTED_MEAS"
echo

if [[ "${REPORT_MEAS,,}" == "${EXPECTED_MEAS,,}" ]]; then
    echo "MATCH: launch measurement matches OVMF+kernel+initrd+cmdline"
    exit 0
fi

echo "MISMATCH: launch measurement differs from expected"
exit 1
