Skip to content

Instantly share code, notes, and snippets.

@celesteking
Created December 24, 2025 22:07
Show Gist options
  • Select an option

  • Save celesteking/b5f60611b80f74b470c9b87cd6b84af2 to your computer and use it in GitHub Desktop.

Select an option

Save celesteking/b5f60611b80f74b470c9b87cd6b84af2 to your computer and use it in GitHub Desktop.
Measure a readied UKI
#!/usr/bin/env bash
#
# Handy (and simple) script to measure a UKI.
# It extracts object sections from an UKI and feeds them to systemd-measure, which outputs PCR #11 hashes.
# Useful for crafting your own TPM stuff that has to be locked to a specific UKI system state.
#
# Invoke it like so:
# ./uki-measure.sh /boot/EFI/Linux/8ec11fb9f2b34a4e9641e2251560d7a5-6.12.51+deb13-amd64.efi --bank=sha256
#
set -euo pipefail
if [ "$#" -lt 1 ]; then
echo "Usage: $0 <uki-file> (systemd-measure args)"
exit 1
fi
SD_MSR=/usr/lib/systemd/systemd-measure
UKI="$1"
shift
TMPDIR=$(mktemp -t -d ukix.XXX)
cleanup() {
rm -rf "$TMPDIR"
}
trap cleanup EXIT
yellow() { echo -ne "\033[93m$1\e[0m"; }
white() { echo -ne "\033[97m$1\e[0m"; }
# Prefer llvm-objcopy if available
OBJCOPY=$(command -v llvm-objcopy || command -v objcopy)
if [ -z "$OBJCOPY" ]; then
echo "objcopy not found"
exit 1
fi
# Discover PE sections
SECTIONS=$(objdump -h "$UKI" \
| awk '/^ *[0-9]+/ { print $2 }' \
| grep -P '^\.(linux|osrel|cmdline|initrd|splash|dtb|uname|sbat|pcrpkey)\b') || :
sd_args=()
oc_args=()
{
yellow "Sections found:"
for sec in $SECTIONS; do
sec=${sec#.}
out="$TMPDIR/$sec"
white " $sec"
oc_args+=( --dump-section ".$sec=$out" )
sd_args+=( "--$sec=$out" )
done
echo
} >&2
"$OBJCOPY" "${oc_args[@]}" "$UKI" "$TMPDIR/uki"
if [ ${#sd_args[@]} -eq 0 ]; then
echo "Error: No valid UKI sections found in $UKI" >&2
exit 1
fi
"$SD_MSR" calculate "${sd_args[@]}" "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment