Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package sdbootutil for openSUSE:Factory checked in at 2025-02-19 16:01:38 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/sdbootutil (Old) and /work/SRC/openSUSE:Factory/.sdbootutil.new.25061 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "sdbootutil" Wed Feb 19 16:01:38 2025 rev:46 rq:1247068 version:1+git20250219.a796c24 Changes: -------- --- /work/SRC/openSUSE:Factory/sdbootutil/sdbootutil.changes 2025-02-11 21:20:54.065020228 +0100 +++ /work/SRC/openSUSE:Factory/.sdbootutil.new.25061/sdbootutil.changes 2025-02-19 16:01:40.195901349 +0100 @@ -1,0 +2,27 @@ +Wed Feb 19 12:20:52 UTC 2025 - [email protected] + +- Update to version 1+git20250219.a796c24: + * generator: exit if /etc/crypttab is missing + * Fix measure-pcr-validator StandardOutput + +------------------------------------------------------------------- +Mon Feb 17 13:58:10 UTC 2025 - [email protected] + +- Update to version 1+git20250217.f216443: + * Remove .conf suffix from grubenv (bsc#1237198) + +------------------------------------------------------------------- +Fri Feb 14 17:03:06 UTC 2025 - [email protected] + +- Update to version 1+git20250214.ef3b642: + * Add banner reporting PCR 15 mismatch + * Generate PCR 15 predictions if crypttab changed + * Create predictions for PCR 15 + * Add measure-pcr-validator service + * Order devices when FIDO2 keys are used + * Set BuildArch to noarch + * Add dracut measure-pcr module with generator + * Add tpm2-pcr-measure crypttab parameter + * Fix help indentation + +------------------------------------------------------------------- Old: ---- sdbootutil-1+git20250210.45458c4.obscpio New: ---- sdbootutil-1+git20250219.a796c24.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ sdbootutil.spec ++++++ --- /var/tmp/diff_new_pack.d0XbfV/_old 2025-02-19 16:01:41.055937333 +0100 +++ /var/tmp/diff_new_pack.d0XbfV/_new 2025-02-19 16:01:41.059937500 +0100 @@ -17,18 +17,20 @@ Name: sdbootutil -Version: 1+git20250210.45458c4 +Version: 1+git20250219.a796c24 Release: 0 Summary: bootctl wrapper for BLS boot loaders License: MIT URL: https://github.com/openSUSE/sdbootutil Source: %{name}-%{version}.tar BuildRequires: systemd-rpm-macros +Requires: %{name}-dracut-measure-pcr Requires: dialog Requires: dracut-pcr-signature Requires: efibootmgr Requires: jq Requires: keyutils +Requires: openssl Requires: pcr-oracle Requires: qrencode Requires: sed @@ -42,6 +44,7 @@ Requires: udev Supplements: (grub2-x86_64-efi-bls and shim) Supplements: (systemd-boot and shim) +BuildArch: noarch ExclusiveArch: aarch64 ppc64le riscv64 x86_64 %{?systemd_requires} @@ -55,6 +58,7 @@ Requires: %{name} = %{version} Requires: btrfsprogs Requires: snapper +BuildArch: noarch %description snapper Plugin scripts for snapper to handle BLS config files @@ -63,6 +67,7 @@ Summary: plugin script for tukit Requires: %{name} = %{version} Requires: tukit +BuildArch: noarch %description tukit Plugin scripts for tukit to handle BLS config files @@ -72,6 +77,7 @@ Requires: %{name} = %{version} # While kernel-install is in udev Requires: udev +BuildArch: noarch %description kernel-install Plugin script for kernel-install. Note: installation of this @@ -80,6 +86,7 @@ %package enroll Summary: Full disk encryption enrollment Requires: %{name} = %{version} +BuildArch: noarch %description enroll Systemd service and script for full disk encryption enrollment. @@ -89,6 +96,7 @@ Requires: %{name} = %{version} Requires: %{name}-enroll = %{version} Requires: jeos-firstboot +BuildArch: noarch %description jeos-firstboot-enroll JEOS module for full disk encryption enrollment. The module @@ -97,15 +105,26 @@ %package bash-completion Summary: Bash completions for sdbootutil +Requires: %{name} = %{version} Requires: bash Requires: bash-completion -Requires: sdbootutil >= %{version}-%{release} +BuildArch: noarch %description bash-completion Bash completions script for sdbootutil. Allows the user to press TAB to see available commands, options and parameters. +%package dracut-measure-pcr +Summary: Dracut module to measure PCR 15 +BuildRequires: pkgconfig +BuildRequires: rpm-config-SUSE +BuildRequires: pkgconfig(dracut) +BuildArch: noarch + +%description dracut-measure-pcr +Dracut module from sdbootutil to measure PCR 15 in non-UKIs systems + %prep %setup -q @@ -136,9 +155,17 @@ # kernel-install install -D -m 755 50-%{name}.install %{buildroot}%{_prefix}/lib/kernel/install.d/50-%{name}.install -#bash completions +# Bash completions install -D -m 755 completions/bash_sdbootutil %{buildroot}%{_datadir}/bash-completion/completions/sdbootutil +# Dracut module +install -D -m 755 module-setup.sh %{buildroot}%{_prefix}/lib/dracut/modules.d/50measure-pcr/module-setup.sh +install -D -m 755 measure-pcr-generator.sh %{buildroot}%{_prefix}/lib/dracut/modules.d/50measure-pcr/measure-pcr-generator.sh +install -D -m 755 measure-pcr-validator.sh %{buildroot}%{_prefix}/lib/dracut/modules.d/50measure-pcr/measure-pcr-validator.sh +install -D -m 644 measure-pcr-validator.service %{buildroot}/%{_prefix}/lib/dracut/modules.d/50measure-pcr/measure-pcr-validator.service + +install -d -m 700 %{buildroot}%{_sharedstatedir}/%{name} + # tmpfiles install -D -m 755 kernel-install-%{name}.conf \ %{buildroot}%{_prefix}/lib/tmpfiles.d/kernel-install-%{name}.conf @@ -178,8 +205,18 @@ %posttrans kernel-install %tmpfiles_create kernel-install-%{name}.conf +%post dracut-measure-pcr +%{?regenerate_initrd_post} + +%posttrans dracut-measure-pcr +%{?regenerate_initrd_posttrans} + +%postun dracut-measure-pcr +%{?regenerate_initrd_post} + %files %license LICENSE +%dir %{_sharedstatedir}/%{name} %{_bindir}/%{name} %{_unitdir}/%{name}-update-predictions.service @@ -215,3 +252,8 @@ %dir %{_datadir}/bash-completion/completions %{_datadir}/bash-completion/completions/sdbootutil +%files dracut-measure-pcr +%dir %{_prefix}/lib/dracut +%dir %{_prefix}/lib/dracut/modules.d +%{_prefix}/lib/dracut/modules.d/50measure-pcr + ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.d0XbfV/_old 2025-02-19 16:01:41.119940010 +0100 +++ /var/tmp/diff_new_pack.d0XbfV/_new 2025-02-19 16:01:41.123940178 +0100 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/openSUSE/sdbootutil.git</param> - <param name="changesrevision">45458c4548e10f8b221293b57ed15488b222cec6</param></service></servicedata> + <param name="changesrevision">a796c245fffc44b73e72973c836dfd03cd27e4cd</param></service></servicedata> (No newline at EOF) ++++++ sdbootutil-1+git20250210.45458c4.obscpio -> sdbootutil-1+git20250219.a796c24.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sdbootutil-1+git20250210.45458c4/measure-pcr-generator.sh new/sdbootutil-1+git20250219.a796c24/measure-pcr-generator.sh --- old/sdbootutil-1+git20250210.45458c4/measure-pcr-generator.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/sdbootutil-1+git20250219.a796c24/measure-pcr-generator.sh 2025-02-19 13:19:26.000000000 +0100 @@ -0,0 +1,55 @@ +#!/bin/bash +set -euo pipefail + +# For a generator, the first parameter `normal-dir` is not optional +[ -n "$1" ] || { echo "Missing normal-dir parameter"; exit 1; } + +[ -f "/etc/crypttab" ] || exit 0; + +# Read /etc/crypttab lines that contains tpm2-device and +# tpm2-measure-pcr. It will order the services as listed in this file +after="" +while read -r name _ _ opts; do + # Only the entries in /etc/crypttab in the initrd should + # participate from the extension for now. The reason is that + # extensions after the switch root cannot participate in abort + # the boot process from initrd itself + [ -f "/etc/initrd-release" ] || continue + [[ "$name" = \#* ]] && continue + [[ "$opts" != *"tpm2-device="* ]] && continue + [[ "$opts" != *"tpm2-measure-pcr="* ]] && continue + mkdir -p "$1/systemd-cryptsetup@$name.service.d" + cat > "$1/systemd-cryptsetup@$name.service.d/measure-pcr.conf" <<-EOF + # Automatically generated by measure-pcr-generator + + [Service] + Environment="SYSTEMD_FORCE_MEASURE=yes" + EOF + if [ -n "$after" ]; then + cat >> "$1/systemd-cryptsetup@$name.service.d/measure-pcr.conf" <<-EOF + + [Unit] + After=systemd-cryptsetup@$after.service + EOF + fi + after="$name" +done < /etc/crypttab + +# Do a similar loop for devices that can be unlocked by FIDO2 keys +after="" +while read -r name _ _ opts; do + [[ "$name" = \#* ]] && continue + [[ "$opts" != *"fido2-device="* ]] && continue + mkdir -p "$1/systemd-cryptsetup@$name.service.d" + [ -f "$1/systemd-cryptsetup@$name.service.d/measure-pcr.conf" ] || { + echo "# Automatically generated by measure-pcr-generator" > "$1/systemd-cryptsetup@$name.service.d/measure-pcr.conf" + } + if [ -n "$after" ]; then + cat >> "$1/systemd-cryptsetup@$name.service.d/measure-pcr.conf" <<-EOF + + [Unit] + After=systemd-cryptsetup@$after.service + EOF + fi + after="$name" +done < /etc/crypttab diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sdbootutil-1+git20250210.45458c4/measure-pcr-validator.service new/sdbootutil-1+git20250219.a796c24/measure-pcr-validator.service --- old/sdbootutil-1+git20250210.45458c4/measure-pcr-validator.service 1970-01-01 01:00:00.000000000 +0100 +++ new/sdbootutil-1+git20250219.a796c24/measure-pcr-validator.service 2025-02-19 13:19:26.000000000 +0100 @@ -0,0 +1,22 @@ +[Unit] +Description=Validate LUKS2 devices +DefaultDependencies=false + +OnFailure=systemd-halt.service + +Wants=cryptsetup.target +After=cryptsetup.target +Before=local-fs.target + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/bin/measure-pcr-validator +Environment=TERM=linux +ExecStopPost=/bin/sh -c "/usr/bin/plymouth quit 2>/dev/null || :" +StandardOutput=tty +StandardInput=tty + +[Install] +# If we use RequiredBy we trigger the debug shell +WantedBy=local-fs.target \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sdbootutil-1+git20250210.45458c4/measure-pcr-validator.sh new/sdbootutil-1+git20250219.a796c24/measure-pcr-validator.sh --- old/sdbootutil-1+git20250210.45458c4/measure-pcr-validator.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/sdbootutil-1+git20250219.a796c24/measure-pcr-validator.sh 2025-02-19 13:19:26.000000000 +0100 @@ -0,0 +1,68 @@ +#!/bin/bash +set -euo pipefail + +WHITE="\e[1;37m" +LIGHT_BLUE="\e[1;34m" +END="\e[m" + +get_measure_pcr_ignore() { + (set +eu; . /lib/dracut-lib.sh; getargbool no measure-pcr-validator.ignore) +} + +validate_measure_pcr_signature() { + openssl dgst -sha256 \ + -verify /var/lib/sdbootutil/measure-pcr-public.pem \ + -signature /var/lib/sdbootutil/measure-pcr-prediction.sha256 \ + /var/lib/sdbootutil/measure-pcr-prediction &> /dev/null +} + +validate_measure_pcr() { + if [ -f "/var/lib/sdbootutil/measure-pcr-prediction.sha256" ] && \ + [ -f "/var/lib/sdbootutil/measure-pcr-public.pem" ]; then + if ! validate_measure_pcr_signature; then + echo "Error: the signature for the prediction file is not valid" + return 1 + fi + else + echo "Warning: the signature for the prediction file is missing" + fi + + if [ ! -e "/sys/class/tpm/tpm0" ]; then + echo "Error: TPM2 not found in /sys/class/tpm/tpm0" + return 1 + fi + + local res=1 + for sha in sha1 sha256 sha384 sha512; do + [ -e "/sys/class/tpm/tpm0/pcr-$sha/15" ] || continue + read -r expected_pcr_15 < "/sys/class/tpm/tpm0/pcr-$sha/15" + grep -Fixq "$expected_pcr_15" /var/lib/sdbootutil/measure-pcr-prediction; res="$?" + break + done + + return "$res" +} + +# The measure-pcr-prediction file contain a list of hashes (sha1, +# sha256, ...) +if [ -f "/var/lib/sdbootutil/measure-pcr-prediction" ] && ! validate_measure_pcr; then + if get_measure_pcr_ignore; then + echo "Warning: the validation of PCR 15 failed. Continuing the boot process" + else + echo "Error: the validation of PCR 15 failed" + + kill -SIGRTMIN+21 1 + sleep 1 + echo -ne '\n\n\a' + echo -e "${WHITE}*********************************************************************${END}" + echo -e "${WHITE}ERROR: PCR 15 mismatch. Encrypted devices compromised${END}" + echo -e "${WHITE}Use${END} '${LIGHT_BLUE}measure-pcr-validator.ignore=yes${END}' ${WHITE}in cmdline to bypass the check${END}" + echo -e "${WHITE}*********************************************************************${END}" + echo + read -n1 -s -r -t 10 -p $'\e[1;37m*** The system will be halted. Press any key ...\e[0m' || true + echo + kill -SIGRTMIN+20 1 + + exit 1 + fi +fi diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sdbootutil-1+git20250210.45458c4/module-setup.sh new/sdbootutil-1+git20250219.a796c24/module-setup.sh --- old/sdbootutil-1+git20250210.45458c4/module-setup.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/sdbootutil-1+git20250219.a796c24/module-setup.sh 2025-02-19 13:19:26.000000000 +0100 @@ -0,0 +1,24 @@ +#!/bin/bash + +# Prerequisite check(s) for module. +check() { + # Return 255 to only include the module, if another module + # requires it. + return 0 +} + +depends() { + return 0 +} + +installkernel() { + inst_multiple grep openssl +} + +install() { + inst_script "$moddir/measure-pcr-generator.sh" "/usr/lib/systemd/system-generators/measure-pcr-generator" + inst_script "$moddir/measure-pcr-validator.sh" "/usr/bin/measure-pcr-validator" + inst_simple "$moddir/measure-pcr-validator.service" "$systemdsystemunitdir/measure-pcr-validator.service" + [ -f "/var/lib/sdbootutil/measure-pcr-public.pem" ] && inst_simple "/var/lib/sdbootutil/measure-pcr-public.pem" + $SYSTEMCTL -q --root "$initdir" enable measure-pcr-validator.service +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sdbootutil-1+git20250210.45458c4/sdbootutil new/sdbootutil-1+git20250219.a796c24/sdbootutil --- old/sdbootutil-1+git20250210.45458c4/sdbootutil 2025-02-10 10:36:24.000000000 +0100 +++ new/sdbootutil-1+git20250219.a796c24/sdbootutil 2025-02-19 13:19:26.000000000 +0100 @@ -22,6 +22,7 @@ arg_ask_key_pin_or_pw= arg_method= arg_signed_policy= +arg_measure_pcr= have_snapshots= # for x in vmlinuz image vmlinux linux bzImage uImage Image zImage; do image= @@ -80,6 +81,8 @@ helpandquit() { + # Tabs are removed from the start of the line. Use spaces to + # indent cat <<-EOF Usage: $0 [OPTIONS] [COMMAND] OPTIONS: @@ -91,115 +94,123 @@ --no-variables Do not update UEFI variables --no-reuse-initrd Always regenerate initrd --sync Synchronize (update, downgrade) the bootloader - --portable Handle bootloader on portable devices (also --removable possible) + --portable Handle bootloader on portable devices + (also --removable possible) --only-default Only list the default entry --default-snapshot [SNAPSHOT] refers to the default snapshot - --ask-key Ask recovery Key when initial enrollment (or randomly generated) + --ask-key Ask recovery Key when initial enrollment + (or randomly generated) --ask-pin Ask recovery PIN for re-enrollment - Ask TPM2 PIN when initial enrollment + Ask TPM2 PIN when initial enrollment --ask-pw Ask password when initial enrollment --method "tpm2", "tpm2+pin", "fido2", "password", "recovery-key" --signed-policy Use signed policy for TPM2 enrollment - --pcr Comma seperated list of PCRs to enroll + --measure-pcr Force update of PCR 15 prediction for LUKS2 volume key + Requires LUKS2 password to accessing the volume key + --pcr Comma seperated list of PCRs to enroll -v, --verbose More verbose output -h, --help This screen COMMAND: bootloader [SNAPSHOT] - Print the detected bootloader + Print the detected bootloader add-kernel VERSION [SNAPSHOT] - Create boot entry for specified kernel + Create boot entry for specified kernel add-all-kernels [SNAPSHOT] - Create boot entries for all kernels in SNAPSHOT + Create boot entries for all kernels in SNAPSHOT mkinitrd [SNAPSHOT] - Create boot entries for all kernels in SNAPSHOT, - assumes --no-reuse-initrd to regenerate initrds + Create boot entries for all kernels in SNAPSHOT, + assumes --no-reuse-initrd to regenerate initrds remove-kernel VERSION [SNAPSHOT] - Remove boot entry for specified kernel + Remove boot entry for specified kernel remove-all-kernels [SNAPSHOT] - Remove boot entries for all kernels in SNAPSHOT + Remove boot entries for all kernels in SNAPSHOT list-kernels [SNAPSHOT] - List all kernels related to SNAPSHOT + List all kernels related to SNAPSHOT list-entries [SNAPSHOT] - List all entries related to SNAPSHOT + List all entries related to SNAPSHOT list-snapshots - List all snapshots + List all snapshots list-devices - List encrypted devices that are tracked + List encrypted devices that are tracked show-entry VERSION [SNAPSHOT] - Show fields for an entry with an specified kernel - version + Show fields for an entry with an specified kernel + version update-entry VERSION [SNAPSHOT] - Update "options" field from /etc/kernel/cmdline for an entry + Update "options" field from /etc/kernel/cmdline + for an entry update-all-entries [SNAPSHOT] - Update "options" field from /etc/kernel/cmdline for all entries + Update "options" field from /etc/kernel/cmdline + for all entries set-default-snapshot [SNAPSHOT] - Make SNAPSHOT the default for next boot. - Also install all kernels if needed + Make SNAPSHOT the default for next boot. + Also install all kernels if needed is-bootable [SNAPSHOT] - Check whether SNAPSHOT has any kernels registered, ie - is potentially bootable + Check whether SNAPSHOT has any kernels registered, ie + is potentially bootable - install Install systemd-boot and shim into ESP + install + Install systemd-boot and shim into ESP needs-update - Check whether the bootloader in ESP needs updating + Check whether the bootloader in ESP needs updating update - Update the bootloader if it's older than the deployed version. - Use the --sync option to replace the deployed version also when it's newer + Update the bootloader if it's older than the deployed + version. Use the --sync to allow downgrades force-update - Update the bootloader in any case + Update the bootloader in any case set-default ID - Set default boot loader entry + Set default boot loader entry get-default - Get default boot loader entry + Get default boot loader entry set-timeout SECONDS - Set the menu timeout + Set the menu timeout get-timeout - Get the menu timeout in seconds + Get the menu timeout in seconds enroll - Enroll a TPM2 (+PIN), a FIDO2 key or a password for - all devices + Enroll a TPM2 (+PIN), a FIDO2 key or a password for + all devices unenroll - Unenroll a TPM2 (+PIN), a FIDO2 key or a password for - all devices + Unenroll a TPM2 (+PIN), a FIDO2 key or a password for + all devices update-predictions - Update TPM2 predictions + Update TPM2 predictions Variables: - SYSTEMD_COLORS Set 0 to disable colored output - KEY Recovery key (initial enrollment; %u:sdbootutil) - PIN TPM2 PIN (initial enrollment; %u:sdbootutil) - PIN Recovery PIN (re-enrollment; %u:sdbootutil) - PW Password / Recovery Key (initial enrollment; %u:sdbootutil) - (%u:cryptenroll for changes via systemd-cryptenroll) + SYSTEMD_COLORS Set 0 to disable colored output + KEY Recovery key (initial enrollment; %u:sdbootutil) + PIN TPM2 PIN (initial enrollment; %u:sdbootutil) + PIN Recovery PIN (re-enrollment; %u:sdbootutil) + PW Password / Recovery Key (initial enrollment; %u:sdbootutil) + (%u:cryptenroll for changes via systemd-cryptenroll) Misc: - Ignoring Devices A LUKS2 device can be un-tracked (ignored) by sdbootutil if - is present in /etc/crypttab and has the "x-sdbootutil.ignore" option + Ignoring Devices A LUKS2 device can be un-tracked (ignored) + by sdbootutil if is present in /etc/crypttab + and has the "x-sdbootutil.ignore" option EOF exit 0 @@ -1369,7 +1380,7 @@ { local s="$1" local i - for ((i=0;i<${#s};i+=2)); do eval echo -n "\$'\x${s:$i:2}'"; done + for ((i=0;i<${#s};i+=2)); do echo -ne "\x${s:$i:2}"; done } update_random_seed() @@ -1462,7 +1473,8 @@ { local id="${1:?}" set_default_sdboot "$id" - grubenv_set "default" "$id" + # Remove the ".conf" suffix (bsc#1237198) + grubenv_set "default" "${id/%.conf/}" } set_default_entry() @@ -1493,7 +1505,8 @@ { local val val="$(grubenv_get "default")" - echo "$val" + # Add ".conf" suffix if necessary (bsc#1237198) + echo "${val/%.conf/}.conf" } get_default_entry() @@ -1682,12 +1695,12 @@ echo -n '{"records":[{"pcr":'"$pcr"',"digests":[' > "$pcrlock" local separator=0 local digest - for a in sha1 sha256 sha384 sha512; do + for dgst in sha1 sha256 sha384 sha512; do [ "$separator" = "0" ] || echo -n "," >> "$pcrlock" separator=1 - hash "${a}sum" || continue - read -r digest _ < <("${a}sum" "$element") - echo -n '{"hashAlg":"'"$a"'","digest":"'"$digest"'"}' >> "$pcrlock" + hash "${dgst}sum" || continue + read -r digest _ < <("${dgst}sum" "$element") + echo -n '{"hashAlg":"'"$dgst"'","digest":"'"$digest"'"}' >> "$pcrlock" done echo ']}]}' >> "$pcrlock" } @@ -2135,6 +2148,122 @@ } } +get_volume_password() +{ + local pw keyid keyid_int + keyid="$(keyctl id %user:sdbootutil 2> /dev/null)" || true + keyid_int="$(keyctl id %user:sdbootutil-pin 2> /dev/null)" || true + if [ -n "$keyid_int" ]; then + pw="$(keyctl pipe "$keyid_int")" + elif [ -n "$keyid" ]; then + pw="$(keyctl pipe "$keyid")" + else + read -r -s -p "Password: " pw + keyctl_add_with_timeout "sdbootutil-pin" "$pw" + fi + echo "$pw" +} + +get_volume_key() +{ + local dev="$1" + local pw out cryptsetup_status + pw="$(get_volume_password)" + out="$(cryptsetup luksDump --batch-mode --dump-master-key "$dev" <<<"$pw")" + cryptsetup_status="$?" + echo "$out" | sed -n '/MK dump:/,$p' | sed -E 's/MK dump:|[[:blank:]]+//g' | sed -z 's/\n//g' + return "$cryptsetup_status" +} + +extend_pcr() +{ + local dgst="$1" + local pcr="$2" + local val="$3" + local digest + + hash "${dgst}sum" || return + hex_to_binary "$pcr$val" > "$tmpdir/pcr" + read -r digest _ < <("${dgst}sum" "$tmpdir/pcr") + echo "$digest" +} + +generate_tpm2_predictions_pcr_15() +{ + local devs=() + local msgs=() + local vks=() + local name dev opts uuid vk pw + # Read /etc/crypttab lines that contains tpm2-device and + # tpm2-measure-pcr. This code is the similar from + # measure-pcr-generator.sh, so we guarantee the same ordering + # for PCR 15 extension + while read -r name dev _ opts; do + # Only the entries in /etc/crypttab in the initrd + # (marked with x-initrd.attach) should participate + # from the extension for now. The reason is that + # extensions after the switch root cannot participate + # in abort the boot process from initrd itself + [[ "$name" = \#* ]] && continue + [[ "$opts" != *"x-initrd.attach"* ]] && continue + [[ "$opts" != *"tpm2-device="* ]] && continue + [[ "$opts" != *"tpm2-measure-pcr="* ]] && continue + devs+=("$dev") + uuid="$(blkid "$dev" -o value -s UUID)" + msgs+=("cryptsetup:$name:$uuid") + done < /etc/crypttab + # We need to separate this into a different loop because we + # cannot nest two reads (one for crypttab and another for the + # password) + for dev in "${devs[@]}"; do + vk="$(get_volume_key "$dev")" || { + keyctl revoke %user:sdbootutil-pin 2> /dev/null || true + return 1 + } + vks+=("$vk") + done + + rm -f /var/lib/sdbootutil/measure-pcr-prediction + rm -f /var/lib/sdbootutil/measure-pcr-prediction.sha256 + local dgsts=("sha1" "sha256" "sha384" "sha512") + local sizes=(40 64 96 128) + local pcr15 hmac + for i in "${!dgsts[@]}"; do + pcr15="$(printf '0%.0s' $(seq 1 "${sizes[i]}"))" + for j in "${!msgs[@]}"; do + hmac="$(echo -ne "${msgs[j]}" | openssl mac -digest "${dgsts[i]}" -macopt hexkey:"${vks[j]}" HMAC)" + pcr15="$(extend_pcr "${dgsts[i]}" "$pcr15" "$hmac")" + done + echo "$pcr15" >> "/var/lib/sdbootutil/measure-pcr-prediction" + done + + if [ -f "/var/lib/sdbootutil/measure-pcr-prediction" ] && [ -f "/var/lib/sdbootutil/measure-pcr-private.pem" ]; then + openssl dgst -sha256 \ + -sign /var/lib/sdbootutil/measure-pcr-private.pem \ + -out /var/lib/sdbootutil/measure-pcr-prediction.sha256 \ + /var/lib/sdbootutil/measure-pcr-prediction + fi + + # Register the hash of the parsed crypttab + local crypttab_sha1 + read -r crypttab_sha1 _ < <(sha1sum /etc/crypttab) + echo "$crypttab_sha1" > /var/lib/sdbootutil/crypttab.sha1 + + # Publish the assets in the ESP, so can be imported by + # dracut-pcr-signature + [ -e /var/lib/sdbootutil/measure-pcr-prediction ] && \ + cp /var/lib/sdbootutil/measure-pcr-prediction "${boot_root}${boot_dst}" + [ -e /var/lib/sdbootutil/measure-pcr-prediction.sha256 ] && \ + cp /var/lib/sdbootutil/measure-pcr-prediction.sha256 "${boot_root}${boot_dst}" +} + +updated_crypttab() +{ + local crypttab_sha1 + read -r crypttab_sha1 _ < <(sha1sum /etc/crypttab) + grep -Fixq "$crypttab_sha1" /var/lib/sdbootutil/crypttab.sha1 2> /dev/null +} + generate_tpm2_predictions() { [ -e /etc/crypttab ] || return 0 @@ -2148,6 +2277,13 @@ generate_tpm2_predictions_pcrlock "${FDE_SEAL_PCR_LIST}" fi + + # Generate a PCR 15 prediction only in certain cases, as for + # now this will ask the password (can be resolved by an + # external tool that extract the password from the TPM2 if the + # policy is still valid) + updated_crypttab || { generate_tpm2_predictions_pcr_15; arg_measure_pcr=; } + [ -f "/var/lib/sdbootutil/measure-pcr-prediction" ] && [ -z "$arg_measure_pcr" ] || generate_tpm2_predictions_pcr_15 } have_tracked_devices() @@ -2272,7 +2408,7 @@ if [ "$arg_method" != "tpm2" ] && [ "$arg_method" != "tpm2+pin" ] && echo "$slots" | grep -q tpm2; then echo "Unlocking using TPM2" unlock_method="--unlock-tpm2-device=auto" - # Same for FIDO2 + # Same for FIDO2 elif [ "$arg_method" != "fido2" ] && echo "$slots" | grep -q fido2; then echo "Unlocking using FIDO2" unlock_method="--unlock-fido2-device=auto" @@ -2537,6 +2673,7 @@ "tpm2"|"tpm2+pin") have_tpm2 || err "No TPM2 found found" add_crypttab_option 'tpm2-device=auto' + add_crypttab_option 'tpm2-measure-pcr=yes' ;; "fido2") @@ -2544,6 +2681,17 @@ add_crypttab_option 'fido2-device=auto' ;; esac + + # For predicting PCR 15 we need to sign a file. Create the + # public and private key if missing. This (as the + # /etc/crypttab change) can require a new initrd + if [ "$arg_method" = "tpm2" ] || [ "$arg_method" = "tpm2+pin" ]; then + local private="/var/lib/sdbootutil/measure-pcr-private.pem" + local public="/var/lib/sdbootutil/measure-pcr-public.pem" + [ -f "$private" ] || openssl genrsa -out "$private" 4096 + [ -f "$public" ] || openssl rsa -in "$private" -pubout -out "$public" + fi + if [ "$arg_no_reuse_initrd" = "1" ]; then install_all_kernels "$root_snapshot" # Avoid the call of generate_tpm2_predictions at the @@ -2620,6 +2768,10 @@ rm -fr /var/lib/pcrlock.d rm -f /var/lib/systemd/pcrlock.json rm -f "${boot_root}${boot_dst}/pcrlock.json" + rm -f /var/lib/sdbootutil/measure-pcr-prediction + rm -f /var/lib/sdbootutil/measure-pcr-prediction.sha256 + rm -f "${boot_root}${boot_dst}/measure-pcr-prediction" + rm -f "${boot_root}${boot_dst}/measure-pcr-prediction.sha256" } unenroll_pcr_oracle() @@ -2629,6 +2781,10 @@ rm -f /etc/systemd/tpm2-pcr-signature.json rm -f "${boot_root}${boot_dst}/tpm2-pcr-public-key.pem" rm -f "${boot_root}${boot_dst}/tpm2-pcr-signature.json" + rm -f /var/lib/sdbootutil/measure-pcr-prediction + rm -f /var/lib/sdbootutil/measure-pcr-prediction.sha256 + rm -f "${boot_root}${boot_dst}/measure-pcr-prediction" + rm -f "${boot_root}${boot_dst}/measure-pcr-prediction.sha256" } unenroll_device() @@ -2677,6 +2833,7 @@ "tpm2"|"tpm2+pin") have_tpm2 || err "No TPM2 found found" remove_crypttab_option 'tpm2-device=auto' + remove_crypttab_option 'tpm2-measure-pcr=yes' ;; "fido2") @@ -2777,6 +2934,7 @@ [ask-pw]="" [method]="_method" [signed-policy]="" + [measure-pcr]="" [pcr]="_none" ) opts_long="" @@ -2836,6 +2994,7 @@ --ask-key|--ask-pin|--ask-pw) arg_ask_key_pin_or_pw=1; shift ;; --method) arg_method="$2"; shift 2 ;; --signed-policy) arg_signed_policy=1; shift ;; + --measure-pcr) arg_measure_pcr=1; shift ;; --pcr) FDE_SEAL_PCR_LIST="$2"; shift 2 ;; --) shift ; break ;; *) echo "Internal error!" ; exit 1 ;; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sdbootutil-1+git20250210.45458c4/sdbootutil.spec new/sdbootutil-1+git20250219.a796c24/sdbootutil.spec --- old/sdbootutil-1+git20250210.45458c4/sdbootutil.spec 2025-02-10 10:36:24.000000000 +0100 +++ new/sdbootutil-1+git20250219.a796c24/sdbootutil.spec 2025-02-19 13:19:26.000000000 +0100 @@ -24,6 +24,7 @@ URL: https://github.com/openSUSE/sdbootutil Source: %{name}-%{version}.tar BuildRequires: systemd-rpm-macros +Requires: %{name}-dracut-measure-pcr Requires: (%{name}-snapper if (snapper and btrfsprogs)) Requires: (%{name}-tukit if read-only-root-fs) Requires: dialog @@ -31,6 +32,7 @@ Requires: efibootmgr Requires: jq Requires: keyutils +Requires: openssl Requires: pcr-oracle Requires: qrencode Requires: sed @@ -42,6 +44,7 @@ Requires: udev Supplements: (grub2-x86_64-efi-bls and shim) Supplements: (systemd-boot and shim) +BuildArch: noarch ExclusiveArch: aarch64 ppc64le riscv64 x86_64 %{?systemd_requires} @@ -55,6 +58,7 @@ Requires: %{name} = %{version} Requires: btrfsprogs Requires: snapper +BuildArch: noarch %description snapper Plugin scripts for snapper to handle BLS config files @@ -63,6 +67,7 @@ Summary: plugin script for tukit Requires: %{name} = %{version} Requires: tukit +BuildArch: noarch %description tukit Plugin scripts for tukit to handle BLS config files @@ -72,6 +77,7 @@ Requires: %{name} = %{version} # While kernel-install is in udev Requires: udev +BuildArch: noarch %description kernel-install Plugin script for kernel-install. Note: installation of this @@ -80,6 +86,7 @@ %package enroll Summary: Full disk encryption enrollment Requires: %{name} = %{version} +BuildArch: noarch %description enroll Systemd service and script for full disk encryption enrollment. @@ -89,6 +96,7 @@ Requires: %{name} = %{version} Requires: %{name}-enroll = %{version} Requires: jeos-firstboot +BuildArch: noarch %description jeos-firstboot-enroll JEOS module for full disk encryption enrollment. The module @@ -97,15 +105,26 @@ %package bash-completion Summary: Bash completions for sdbootutil -Requires: sdbootutil >= %{version}-%{release} +Requires: %{name} = %{version} Requires: bash Requires: bash-completion +BuildArch: noarch %description bash-completion Bash completions script for sdbootutil. Allows the user to press TAB to see available commands, options and parameters. +%package dracut-measure-pcr +Summary: Dracut module to measure PCR 15 +BuildRequires: pkgconfig +BuildRequires: rpm-config-SUSE +BuildRequires: pkgconfig(dracut) +BuildArch: noarch + +%description dracut-measure-pcr +Dracut module from sdbootutil to measure PCR 15 in non-UKIs systems + %prep %setup -q @@ -136,9 +155,17 @@ # kernel-install install -D -m 755 50-%{name}.install %{buildroot}%{_prefix}/lib/kernel/install.d/50-%{name}.install -#bash completions +# Bash completions install -D -m 755 completions/bash_sdbootutil %{buildroot}%{_datadir}/bash-completion/completions/sdbootutil +# Dracut module +install -D -m 755 module-setup.sh %{buildroot}%{_prefix}/lib/dracut/modules.d/50measure-pcr/module-setup.sh +install -D -m 755 measure-pcr-generator.sh %{buildroot}%{_prefix}/lib/dracut/modules.d/50measure-pcr/measure-pcr-generator.sh +install -D -m 755 measure-pcr-validator.sh %{buildroot}%{_prefix}/lib/dracut/modules.d/50measure-pcr/measure-pcr-validator.sh +install -D -m 644 measure-pcr-validator.service %{buildroot}/%{_prefix}/lib/dracut/modules.d/50measure-pcr/measure-pcr-validator.service + +install -d -m 700 %{buildroot}%{_sharedstatedir}/%{name} + # tmpfiles install -D -m 755 kernel-install-%{name}.conf \ %{buildroot}%{_prefix}/lib/tmpfiles.d/kernel-install-%{name}.conf @@ -178,8 +205,18 @@ %posttrans kernel-install %tmpfiles_create kernel-install-%{name}.conf +%post dracut-measure-pcr +%{?regenerate_initrd_post} + +%posttrans dracut-measure-pcr +%{?regenerate_initrd_posttrans} + +%postun dracut-measure-pcr +%{?regenerate_initrd_post} + %files %license LICENSE +%dir %{_sharedstatedir}/%{name} %{_bindir}/%{name} %{_unitdir}/%{name}-update-predictions.service @@ -215,4 +252,9 @@ %dir %{_datadir}/bash-completion/completions %{_datadir}/bash-completion/completions/sdbootutil +%files dracut-measure-pcr +%dir %{_prefix}/lib/dracut +%dir %{_prefix}/lib/dracut/modules.d +%{_prefix}/lib/dracut/modules.d/50measure-pcr + %changelog ++++++ sdbootutil.obsinfo ++++++ --- /var/tmp/diff_new_pack.d0XbfV/_old 2025-02-19 16:01:41.263946036 +0100 +++ /var/tmp/diff_new_pack.d0XbfV/_new 2025-02-19 16:01:41.267946203 +0100 @@ -1,5 +1,5 @@ name: sdbootutil -version: 1+git20250210.45458c4 -mtime: 1739180184 -commit: 45458c4548e10f8b221293b57ed15488b222cec6 +version: 1+git20250219.a796c24 +mtime: 1739967566 +commit: a796c245fffc44b73e72973c836dfd03cd27e4cd
