Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package sdbootutil for openSUSE:Factory 
checked in at 2024-07-18 19:15:13
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/sdbootutil (Old)
 and      /work/SRC/openSUSE:Factory/.sdbootutil.new.17339 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "sdbootutil"

Thu Jul 18 19:15:13 2024 rev:24 rq:1188375 version:1+git20240718.6fbaad1

Changes:
--------
--- /work/SRC/openSUSE:Factory/sdbootutil/sdbootutil.changes    2024-07-17 
15:14:32.236723195 +0200
+++ /work/SRC/openSUSE:Factory/.sdbootutil.new.17339/sdbootutil.changes 
2024-07-18 19:15:17.368604812 +0200
@@ -1,0 +2,18 @@
+Thu Jul 18 10:05:20 UTC 2024 - apla...@suse.com
+
+- Update to version 1+git20240718.6fbaad1:
+  * Enroll using pcr_oracle if pcrlock fails
+  * Fix loader.conf measurement
+  * Address some shellcheck issues
+  * Implement basic [un]enroll commands
+  * snapper: do not error if sdbootutil fails
+
+-------------------------------------------------------------------
+Tue Jul 16 12:25:53 UTC 2024 - apla...@suse.com
+
+- Update to version 1+git20240716.bb40c38:
+  * Add --only-default option for list-entries command
+  * Turn off colors when the shell it not interactive
+  * Support portable installation of bootloader This is useful to create 
portable drives, so the bootloader entry isn't created permenantly.
+
+-------------------------------------------------------------------

Old:
----
  sdbootutil-1+git20240704.a2c5a26.obscpio

New:
----
  sdbootutil-1+git20240718.6fbaad1.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ sdbootutil.spec ++++++
--- /var/tmp/diff_new_pack.KMOSfE/_old  2024-07-18 19:15:19.440689232 +0200
+++ /var/tmp/diff_new_pack.KMOSfE/_new  2024-07-18 19:15:19.456689884 +0200
@@ -27,7 +27,7 @@
 %define git_version %{nil}
 %endif
 Name:           sdbootutil
-Version:        1+git20240704.a2c5a26%{git_version}
+Version:        1+git20240718.6fbaad1%{git_version}
 Release:        0
 Summary:        script to install shim with sd-boot
 License:        MIT

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.KMOSfE/_old  2024-07-18 19:15:19.836705366 +0200
+++ /var/tmp/diff_new_pack.KMOSfE/_new  2024-07-18 19:15:19.868706670 +0200
@@ -3,6 +3,6 @@
                 <param 
name="url">https://github.com/lnussel/sdbootutil.git</param>
               <param 
name="changesrevision">708592a5033bb41d14e378172466ae9e90dfb3c4</param></service><service
 name="tar_scm">
                 <param 
name="url">https://github.com/openSUSE/sdbootutil.git</param>
-              <param 
name="changesrevision">a2c5a26866076afd91446dea57a44ac91746a4bf</param></service></servicedata>
+              <param 
name="changesrevision">6fbaad1a48cb99629775d6584cdbc90de826a1d8</param></service></servicedata>
 (No newline at EOF)
 

++++++ sdbootutil-1+git20240704.a2c5a26.obscpio -> 
sdbootutil-1+git20240718.6fbaad1.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/sdbootutil-1+git20240704.a2c5a26/10-sdbootutil.snapper 
new/sdbootutil-1+git20240718.6fbaad1/10-sdbootutil.snapper
--- old/sdbootutil-1+git20240704.a2c5a26/10-sdbootutil.snapper  2024-07-04 
14:00:45.000000000 +0200
+++ new/sdbootutil-1+git20240718.6fbaad1/10-sdbootutil.snapper  2024-07-18 
12:02:41.000000000 +0200
@@ -21,7 +21,7 @@
 
        is_transactional && return 0
 
-       /usr/bin/sdbootutil add-all-kernels "$num"
+       /usr/bin/sdbootutil add-all-kernels "$num" || :
 }
 
 delete_snapshot()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sdbootutil-1+git20240704.a2c5a26/sdbootutil 
new/sdbootutil-1+git20240718.6fbaad1/sdbootutil
--- old/sdbootutil-1+git20240704.a2c5a26/sdbootutil     2024-07-04 
14:00:45.000000000 +0200
+++ new/sdbootutil-1+git20240718.6fbaad1/sdbootutil     2024-07-18 
12:02:41.000000000 +0200
@@ -20,14 +20,23 @@
 arg_no_variables=
 arg_no_reuse_initrd=
 arg_no_random_seed=
-arg_ask_pin=
+arg_portable=
+arg_only_default=
+arg_ask_pin_or_pw=
+arg_method=
+arg_signed_policy=
 have_snapshots=
 # for x in vmlinuz image vmlinux linux bzImage uImage Image zImage; do
 image=
 
 color_red=
 color_end=
-if [ "$SYSTEMD_COLORS" != "false" ] && [ "$SYSTEMD_COLORS" != "0" ]; then
+# The shell is interactive and the colors haven't been disabled forcefully
+# or the shell is not interactive but the colors have been forcefully enabled
+if { [[ "$-" == *i* ]] \
+    && [ "$SYSTEMD_COLORS" != "false" ] && [ "$SYSTEMD_COLORS" != "0" ]; } \
+    || [[ "$-" != *i* ]] \
+    && { [ "$SYSTEMD_COLORS" = "true" ] || [ "$SYSTEMD_COLORS" = "1" ]; }; then
        color_red="\e[31m"
        color_green="\e[32m"
        color_yellow="\e[33m"
@@ -38,8 +47,11 @@
 # State file for transactional systems
 state_file="/var/lib/misc/transactional-update.state"
 
+update_initrd=
 update_predictions=
 
+luks2_devices=()
+
 rollback=()
 
 tmpdir=$(mktemp -d -t sdbootutil.XXXXXX)
@@ -76,7 +88,13 @@
                  --entry-keys          Comma separated list of keys
                  --no-variables        Do not update UEFI variables
                  --no-reuse-initrd     Always regenerate initrd
+                 --portable            Handle bootloader on portable devices
+                 --only-default        Only list the default entry
                  --ask-pin             Ask recovery PIN for re-enrollment
+                                       Ask TPM2 PIN when initial enrollment
+                 --ask-pw              Ask password when initial enrollment
+                 --method              "tpm2", "tpm2+pin", "fido2", "password"
+                 --signed-policy       Use signed policy for TPM2 enrollment
                  -v, --verbose         More verbose output
                  -h, --help            This screen
 
@@ -132,6 +150,14 @@
                force-update
                            Update the bootloader in any case
 
+               enroll
+                           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
+
                update-predictions
                            Update TPM2 predictions
 
@@ -143,6 +169,8 @@
                Variables:
                SYSTEMD_COLORS          Set 0 to disable colored output
                PIN                     Recovery PIN / password (re-enrollment)
+               PIN                     TPM2 PIN (initial enrollment; %u:pin)
+               PW                      Password (initial enrollment; %u:pw)
        EOF
        exit 0
 }
@@ -378,7 +406,8 @@
 {
        local kernel_version="${1:?}"
        local snapshot="$2"
-       local id="$(entry_conf_file "$kernel_version" "$snapshot")"
+       local id
+       id="$(entry_conf_file "$kernel_version" "$snapshot")"
 
        update_entries_for_snapshot "$snapshot"
 
@@ -438,7 +467,8 @@
        local kernel_version="$2"
        [ -n "$kernel_version" ] || err "Missing kernel version"
        settle_entry_token "${snapshot}"
-       local id="$(entry_conf_file "$kernel_version" "$snapshot")"
+       local id
+       id="$(entry_conf_file "$kernel_version" "$snapshot")"
        run_command_output bootctl unlink "$id"
 
        # This action will require to update the PCR predictions
@@ -508,7 +538,7 @@
 
        for file in "${os_release_files[@]}"; do
                [ -f "$file" ] || continue
-               eval $(sed -ne '/^[A-Z_]\+=/s/^/os_release_/p' < "$file")
+               eval "$(sed -ne '/^[A-Z_]\+=/s/^/os_release_/p' < "$file")"
                break
        done
 }
@@ -576,10 +606,10 @@
        local snapshot_dir="$1"
 
        # don't mount if we are within a transactional-update shell
-        [ -z "$TRANSACTIONAL_UPDATE" ] || return 0
+       [ -z "$TRANSACTIONAL_UPDATE" ] || return 0
 
        IFS=',' read -ra fields <<< \
-          $(findmnt --tab-file "${snapshot_dir}/etc/fstab" --noheadings 
--nofsroot --output OPTIONS /etc | sed 's#/sysroot##g' | sed 
's#:/etc,#:'"${snapshot_dir}"'/etc,#g')
+          "$(findmnt --tab-file "${snapshot_dir}/etc/fstab" --noheadings 
--nofsroot --output OPTIONS /etc | sed 's#/sysroot##g' | sed 
's#:/etc,#:'"${snapshot_dir}"'/etc,#g')"
 
        local lower=""
        local upper=""
@@ -596,7 +626,7 @@
 {
        local snapshot_dir="$1"
        # don't umount if we are within a transactional-update shell
-        [ -z "$TRANSACTIONAL_UPDATE" ] || return 0
+       [ -z "$TRANSACTIONAL_UPDATE" ] || return 0
        umount "${snapshot_dir}/etc"
 }
 
@@ -648,7 +678,7 @@
        local id
        while read -r id; do
                free_space="$(boot_free_space)"
-               if [ "$total_size" -gt "$free_space" ]; then
+               if [ "$total_size" -gt "$free_space" ]; then
                        log_info "Removing boot entry $id"
                        bootctl unlink "$id"
                else
@@ -812,6 +842,7 @@
 
 list_entries()
 {
+       # The password is read from "cryptenroll" kernel keyring
        if [ ! -s "$entryfile" ]; then
                if [ -n "$1" ]; then
                        update_entries_for_snapshot "$1"
@@ -827,6 +858,8 @@
                color=
                if [ "$isdefault" = "true" ]; then
                        color="$color_bu"
+               elif [ -n "$arg_only_default" ]; then
+                       continue
                fi
                if [ "$isreported" = "false" ]; then
                        color="$color${color_green}"
@@ -868,7 +901,8 @@
        local kernel_version="$2"
        [ -n "$kernel_version" ] || err "Missing kernel version"
        settle_entry_token "${snapshot}"
-       local id="$(entry_conf_file "$kernel_version" "$snapshot")"
+       local id
+       id="$(entry_conf_file "$kernel_version" "$snapshot")"
 
        local conf
        conf="$(find_conf_file "${kernel_version}" "${snapshot}")"
@@ -882,7 +916,7 @@
                        *) continue ;;
                esac
 
-               if [ -z "$arg_entry_keys" ] || [[ ${arg_entry_keys[@]} =~ "all" 
]] || [[ ${arg_entry_keys[@]} =~ "$k" ]]; then
+               if [ -z "$arg_entry_keys" ] || [[ ${arg_entry_keys[*]} == 
*"all"* ]] || [[ ${arg_entry_keys[*]} == *"$k"* ]]; then
                        echo -e "$k\t$v"
                fi
        done < "$conf"
@@ -1079,9 +1113,9 @@
 
 calc_chksum()
 {
-    # shellcheck disable=SC2046
-    set -- $(sha1sum "$1")
-    chksum="$1"
+       # shellcheck disable=SC2046
+       set -- $(sha1sum "$1")
+       chksum="$1"
 }
 
 # map with kernel version as key and checksum as value
@@ -1283,7 +1317,8 @@
 {
        local prefix=""
        [ -z "$have_snapshots" ] || 
prefix="/.snapshots/${1-$root_snapshot}/snapshot"
-       local grub2="$prefix/usr/share/efi/$(uname -m)/grub.efi"
+       local grub2
+       grub2="$prefix/usr/share/efi/$(uname -m)/grub.efi"
        [ -e "$grub2" ] || grub2="$prefix/usr/share/grub2/$(uname 
-m)-efi/grub.efi"
        echo "$grub2"
 }
@@ -1349,7 +1384,7 @@
                log_info "Installing $bldr_name with shim into $boot_root"
                entry="$boot_dst/shim.efi"
                for i in MokManager shim; do
-                       install -p -D "$prefix$shimdir/$i.efi" 
"$boot_root$boot_dst/$i.efi"
+                       [ -n "$arg_portable" ] || install -p -D 
"$prefix$shimdir/$i.efi" "$boot_root$boot_dst/$i.efi"
                done
                install -p -D "$bootloader" "$boot_root$boot_dst/grub.efi"
 
@@ -1361,14 +1396,15 @@
        else
                log_info "Installing $bldr_name into $boot_root"
                entry="$boot_dst/${bootloader##*/}"
-               install -p -D "$bootloader" "$boot_root$entry"
+               [ -n "$arg_portable" ] || install -p -D "$bootloader" 
"$boot_root$entry"
                install -p -D "$bootloader" 
"$boot_root/EFI/BOOT/BOOT${firmware_arch^^}.EFI"
        fi
+
        # this is for shim to create the entry if missing
-       echo "${entry##*/},openSUSE Boot Manager" | { echo -ne "\xff\xfe"; 
iconv -f ascii -t ucs-2le; } > "$boot_root/$boot_dst/boot.csv"
+       [ -n "$arg_portable" ] || echo "${entry##*/},openSUSE Boot Manager" | { 
echo -ne "\xff\xfe"; iconv -f ascii -t ucs-2le; } > 
"$boot_root$boot_dst/boot.csv"
 
        mkdir -p "$boot_root/$entry_token"
-       echo "$entry_token" > "$boot_root/$boot_dst/installed_by_sdbootutil"
+       echo "$entry_token" > "$boot_root$boot_dst/installed_by_sdbootutil"
        mkdir -p "/etc/kernel"
        [ -s /etc/kernel/entry-token ] || echo "$entry_token" > 
/etc/kernel/entry-token
        update_random_seed
@@ -1385,7 +1421,7 @@
                #
                # NOTE: if this file change, update the linearized
                # version in pcrlock_grub2_exec_cmdline
-               [ -e "$boot_root$boot_dst/grub.cfg" ] || cat > 
"$boot_root$boot_dst/grub.cfg" <<-EOF
+               [ -e "$boot_root$boot_dst/grub.cfg" ] || cat > 
"$boot_root$boot_dst/grub.cfg" <<-EOF
                timeout=8
                function load_video {
                  # A load_video call is added for each bls entry
@@ -1402,7 +1438,7 @@
        fi
 
        # Create boot menu entry if it does not exist
-       [ -n "$arg_no_variables" ] || efibootmgr | grep -q 'Boot.*openSUSE Boot 
Manager' || efibootmgr -q --create --disk "$drive" --part "$partno" --label 
"openSUSE Boot Manager" --loader "$entry" || true
+       [ -n "$arg_no_variables" ] || [ -n "$arg_portable" ] || efibootmgr | 
grep -q 'Boot.*openSUSE Boot Manager' || efibootmgr -q --create --disk "$drive" 
--part "$partno" --label "openSUSE Boot Manager" --loader "$entry" || true
 
        # This action will require to update the PCR predictions
        update_predictions=1
@@ -1485,19 +1521,26 @@
 
 have_pcrlock()
 {
-       [ -e /usr/lib/systemd/systemd-pcrlock ]
+       [ -e /usr/bin/systemd-pcrlock ] || [ -e 
/usr/lib/systemd/systemd-pcrlock ]
+}
+
+have_pcr_oracle()
+{
+       [ -e /usr/bin/pcr-oracle ]
 }
 
 pcrlock()
 {
-       SYSTEMD_LOG_LEVEL="${SYSTEMD_LOG_LEVEL:-warning}" 
/usr/lib/systemd/systemd-pcrlock "$@"
+       local pcrlock_cmd="/usr/bin/systemd-pcrlock"
+       [ -e "$pcrlock_cmd" ] || pcrlock_cmd="/usr/lib/systemd/systemd-pcrlock"
+       SYSTEMD_LOG_LEVEL="${SYSTEMD_LOG_LEVEL:-warning}" "$pcrlock_cmd" "$@"
 }
 
 is_pcr_oracle()
 {
        [ -e /etc/systemd/tpm2-pcr-public-key.pem ] && \
            [ -e /etc/systemd/tpm2-pcr-private-key.pem ] && \
-           [ -e /usr/bin/pcr-oracle ]
+           have_pcr_oracle
 }
 
 regex_entries_ids_for_prediction()
@@ -1525,7 +1568,7 @@
                done
        else
                while read -r id; do
-                       if [ "${#snaphosts[@]}" -lt 3 ]; then
+                       if [ "${#snapshots[@]}" -lt 3 ]; then
                                snapshots[$id]=1
                        fi
                done < <(jq -r '.root|sort_by(.date)[-2:]|.[]|.number' 
"$snapperfile")
@@ -1628,9 +1671,9 @@
                locks+=( "$tmpdir/element-$n.pcrlock" )
        done
        jq --slurp '{"records": [.[].records[0]]}' \
-          ${locks[@]} \
+          "${locks[@]}" \
           > 
"/var/lib/pcrlock.d/710-grub2-kernel-initrd-entry.pcrlock.d/kernel-initrd-$suffix.pcrlock"
-       rm ${locks[@]}
+       rm "${locks[@]}"
 }
 
 pcrlock_grub2_exec_cmdline()
@@ -1665,9 +1708,9 @@
                rm "$tmpdir/line"
        done
        jq --slurp '{"records": [.[].records[0]]}' \
-          ${locks[@]} \
+          "${locks[@]}" \
           > 
"/var/lib/pcrlock.d/650-grub2-entry-exec-cmdline.pcrlock.d/exec-cmdline-$suffix.pcrlock"
-       rm ${locks[@]}
+       rm "${locks[@]}"
 }
 
 pcrlock_grub2_entry_files()
@@ -1692,18 +1735,18 @@
        done < <(jq --raw-output 'map(.path) | .[]' "$entries")
 
        jq --slurp '{"records": [.[].records[0]]}' \
-          ${locks[@]} \
+          "${locks[@]}" \
           > 
"/var/lib/pcrlock.d/643-grub2-entry-files.pcrlock.d/generated$suffix.pcrlock"
-       rm ${locks[@]}
+       rm "${locks[@]}"
 }
 
 pcrlock_sdboot()
 {
        # 641-sdboot-loader-conf.pcrlock is not part of the pcrlock
        # standards
-       if [ -e "{$boot_root}/loader/loader.conf" ]; then
+       if [ -e "${boot_root}/loader/loader.conf" ]; then
                pcrlock \
-                       lock-raw "{$boot_root}/loader/loader.conf" \
+                       lock-raw "${boot_root}/loader/loader.conf" \
                        --pcr=5 \
                        
--pcrlock=/var/lib/pcrlock.d/641-sdboot-loader-conf.pcrlock
        fi
@@ -1843,17 +1886,19 @@
        pcrlock lock-firmware-config
        # If secure boot is disabled, this can fail.  There is patch
        # for the policy generation, and for the authority is planned
-       /usr/lib/systemd/systemd-pcrlock lock-secureboot-policy &> /dev/null || 
true
-       /usr/lib/systemd/systemd-pcrlock lock-secureboot-authority &> /dev/null 
|| true
+       pcrlock lock-secureboot-policy &> /dev/null || true
+       pcrlock lock-secureboot-authority &> /dev/null || true
        # uses / by default
        pcrlock lock-gpt
 
        # 630-shim-efi-application is not part of the pcrlock standards
        # TODO: move to shim-pcrlock.rpm
+       local entry="shim.efi"
+       [ -f "${boot_root}${boot_dst}/${entry}" ] || 
entry="BOOT${firmware_arch^^}.EFI"
        pcrlock \
            lock-pe \
            
--pcrlock=/var/lib/pcrlock.d/630-shim-efi-application.pcrlock.d/generated.pcrlock
 \
-           "${boot_root}${boot_dst}/shim.efi"
+           "${boot_root}${boot_dst}/${entry}"
 
        # 640-boot-loader-efi-application is not part of the pcrlock
        # standards
@@ -1872,21 +1917,23 @@
 
        # If the prediction fails, the system will ask for a password,
        # but we can do a re-enrollment using the recovery PIN.  To
-       # register a recovery PIN disk-encryption-tool will call this
-       # script deploying in the @u keyring a "cryptsetup" entry.
-       # For re-enrollments we can use the same entry, the PIN
-       # environment variable, or the --ask-pin parameter.
+       # register a recovery PIN the installer (disk-encryption-tool,
+       # YaST) will call this script deploying in the %u keyring
+       # "cryptenroll" entry.  For re-enrollments we can use the same
+       # entry, the PIN environment variable, or the --ask-pin
+       # parameter.
        local pin
        local extra=()
-       local keyid="$(keyctl id %user:cryptenroll 2> /dev/null)" || true
+       local keyid
+       keyid="$(keyctl id %user:cryptenroll 2> /dev/null)" || true
        if [ -n "$keyid" ]; then
                pin="$(keyctl pipe "$keyid")"
                extra=("--recovery-pin=yes")
        elif [ -n "$PIN" ]; then
                pin="$PIN"
                extra=("--recovery-pin=yes")
-       elif [ -n "$arg_ask_pin" ]; then
-               read -s -p "Recovery PIN: " pin
+       elif [ -n "$arg_ask_pin_or_pw" ]; then
+               read -r -s -p "Recovery PIN: " pin
                extra=("--recovery-pin=yes")
        fi
 
@@ -1915,7 +1962,7 @@
        while read -r dev; do
                pcrs=$(cryptsetup luksDump --dump-json-metadata "$dev" | jq -r 
"$jq_pcr")
                [ -z "$pcrs" ] || echo "$pcrs"
-       done <<<$(blkid -t TYPE=crypto_LUKS -o device)
+       done <<<"$(blkid -t TYPE=crypto_LUKS -o device)"
 }
 
 generate_tpm2_predictions_pcr_oracle()
@@ -1974,7 +2021,7 @@
        if is_pcr_oracle; then
                generate_tpm2_predictions_pcr_oracle
        elif have_pcrlock; then
-               [ -e /etc/sysconfig/fde-tools ] || { log_info 
"/etc/sysconfig/fde-tools not found. System not enrolled"; return 0; }
+               [ -e /etc/sysconfig/fde-tools ] || { log_info 
"/etc/sysconfig/fde-tools not found"; return 0; }
                # shellcheck disable=SC1091
                . /etc/sysconfig/fde-tools
 
@@ -1982,6 +2029,396 @@
        fi
 }
 
+have_luks2()
+{
+       [ "${#luks2_devices[@]}" -gt 0 ]
+}
+
+detect_luks2()
+{
+       local dev fstype
+       [ -z "$luks2_devices" ] || return 0
+       while read -r dev fstype; do
+               [ "$fstype" = 'crypto_LUKS' ] || continue
+               cryptsetup isLuks --type luks2 "$dev" || continue
+               luks2_devices+=("$dev")
+       done < <(lsblk --noheadings -o PATH,FSTYPE)
+       have_luks2
+}
+
+have_tpm2()
+{
+       [ -n "$(systemd-cryptenroll --tpm2-device=list 2>/dev/null)" ]
+}
+
+have_fido2()
+{
+       [ -n "$(systemd-cryptenroll --fido2-device=list 2>/dev/null)" ]
+}
+
+add_crypttab_option()
+{
+       # This version will share the same options for all crypto_LUKS
+       # devices.  This imply that all of them will be unlocked by the
+       # same TPM2, or the same FIDO2 key
+       local option="$1"
+
+       local crypttab
+       crypttab="$(mktemp -t crypttab.XXXXXX)"
+       echo "# File created by sdbootutil.  Comments will be removed" > 
"$crypttab"
+
+       local name
+       local device
+       local key
+       local opts
+       while read -r name device key opts; do
+               [[ "$name" = \#* ]] && continue
+               if [[ "$opts" != *"$option"* ]]; then
+                       [ -z "$opts" ] && opts="$option" || opts="$opts,$option"
+                       # crypttab has changed so initrd needs to be updated
+                       update_initrd=1
+               fi
+               echo "$name $device ${key:-none} $opts" >> "$crypttab"
+       done < /etc/crypttab
+
+       mv "$crypttab" /etc/crypttab
+       chmod 644 /etc/crypttab
+}
+
+remove_crypttab_option()
+{
+       # Similar to add_crypttab_option, the option will be removed
+       # from all the entries
+       local option="$1"
+
+       local crypttab
+       crypttab="$(mktemp -t crypttab.XXXXXX)"
+       echo "# File created by sdbootutil.  Comments will be removed" > 
"$crypttab"
+
+       local name
+       local device
+       local key
+       local opts
+       while read -r name device key opts; do
+               [[ "$name" = \#* ]] && continue
+               if [[ "$opts" == *"$option"* ]]; then
+                       opts="${opts//,$option}"
+                       opts="${opts//$option}"
+                       # crypttab has changed so initrd needs to be updated
+                       update_initrd=1
+               fi
+               echo "$name $device ${key:-none} $opts" >> "$crypttab"
+       done < /etc/crypttab
+
+       mv "$crypttab" /etc/crypttab
+       chmod 644 /etc/crypttab
+}
+
+generate_rsa_key()
+{
+       pcr-oracle \
+               --rsa-generate-key \
+               --private-key /etc/systemd/tpm2-pcr-private-key.pem \
+               --public-key /etc/systemd/tpm2-pcr-public-key.pem \
+               store-public-key
+}
+
+enroll_pcrlock()
+{
+       local dev="$1"
+       local tpm_pin="$2"
+       local extra_args=()
+
+       if [ -z "$tpm_pin" ]; then
+               echo "Enrolling with TPM2 (pcrlock): $dev"
+       else
+               echo "Enrolling with TPM2+PIN (pcrlock): $dev"
+               extra_args+=(--tpm2-with-pin=1)
+       fi
+
+       # The password is read from "cryptenroll" kernel keyring
+       # XXX: Wipe is separated by now (possible systemd bug)
+       systemd-cryptenroll \
+               --wipe-slot=tpm2 \
+               "$dev"
+
+       # Note that the PCRs are now not stored in the LUKS2 header
+       NEWPIN="$tpm_pin" systemd-cryptenroll \
+               --tpm2-device=auto \
+               "${extra_args[@]}" \
+               --tpm2-pcrlock=/var/lib/systemd/pcrlock.json \
+               "$dev"
+}
+
+enroll_pcroracle()
+{
+       local dev="$1"
+       local tpm_pin="$2"
+       local extra_args=()
+
+       if [ -z "$tpm_pin" ]; then
+               echo "Enrolling with TPM2 (pcr-oracle): $dev"
+       else
+               echo "Enrolling with TPM2+PIN (pcr-oracle): $dev"
+               extra_args+=(--tpm2-with-pin=1)
+       fi
+
+       # The password is read from "cryptenroll" kernel keyring
+       # XXX: Wipe is separated by now (possible systemd bug)
+       systemd-cryptenroll \
+               --wipe-slot=tpm2 \
+               "$dev"
+
+       # Note that the PCRs are now not stored in the LUKS2 header
+       NEWPIN="$tpm_pin" systemd-cryptenroll \
+               --tpm2-device=auto \
+               "${extra_args[@]}" \
+               --tpm2-public-key=/etc/systemd/tpm2-pcr-public-key.pem \
+               --tpm2-public-key-pcrs="${FDE_SEAL_PCR_LIST}" \
+               "$dev"
+}
+
+enroll_fido2()
+{
+       local dev="$1"
+
+       echo "Enrolling with FIDO2: $dev"
+
+       # The password is read from "cryptenroll" kernel keyring
+       # XXX: Wipe is separated by now (possible systemd bug)
+       systemd-cryptenroll \
+               --wipe-slot=fido2 \
+               "$dev"
+
+       # The password is read from "cryptenroll" kernel keyring
+       systemd-cryptenroll --fido2-device=auto "$dev"
+}
+
+enroll_password()
+{
+       local dev="$1"
+       local pw="$2"
+
+       echo "Enrolling with password: $dev"
+
+       # The password is read from "cryptenroll" kernel keyring
+       NEWPASSWORD="$pw" systemd-cryptenroll --wipe-slot=password --password 
"$dev"
+}
+
+enroll_device()
+{
+       local dev="$1"
+       local pin_or_pw="$2"
+
+       case "$arg_method" in
+               "tpm2"|"tpm2+pin")
+                       if [ -z "$arg_signed_policy" ] && have_pcrlock; then
+                               enroll_pcrlock "$dev" "$pin_or_pw" || {
+                                       echo "Enrollment with systemd-pcrlock 
failed"
+                                       echo "Re-trying with pcr-oracle"
+                                       unernroll_pcrlock
+                                       enroll_pcr_oracle "$dev" "$pin_or_pw"
+                               }
+                       elif have_pcr_oracle; then
+                               enroll_pcr_oracle "$dev" "$pin_or_pw"
+                       else
+                               log_info "No TMP2 enrollment mechanism found"
+                       fi
+                       ;;
+
+               "fido2")
+                       enroll_fido2 "$dev"
+                       ;;
+
+               "password")
+                       enroll_password "$dev" "$pin_or_pw"
+                       ;;
+
+               *)
+                       err "Unexpected parameter for --method=: $arg_method"
+                       ;;
+       esac
+}
+
+enroll()
+{
+       [ -e /etc/crypttab ] || { log_info "/etc/crypttab not found. No 
encrypted devices?"; return 0; }
+       [ -e /usr/bin/systemd-cryptenroll ] || { log_info "systemd-cryptenroll 
not found"; return 0; }
+       detect_luks2 || { log_info "No LUKS2 devices found"; return 0; }
+
+       have_pcrlock || have_pcr_oracle || err "Nor systemd-pcrlock not 
pcr-oracle found"
+
+       # Prepare /etc/crypttab and update initrd if required
+       case "$arg_method" in
+               "tpm2"|"tpm2+pin")
+                       have_tpm2 || err "No TPM2 found found"
+                       add_crypttab_option 'tpm2-device=auto'
+                       ;;
+
+               "fido2")
+                       have_fido2 || err "No FIDO2 key found"
+                       add_crypttab_option 'fido2-device=auto'
+                       ;;
+       esac
+       if [ "$update_initrd" = "1" ]; then
+               arg_no_reuse_initrd=1
+               install_all_kernels "$root_snapshot"
+               # Avoid the call of generate_tpm2_predictions at the
+               # end of the script
+               update_predictions=
+       fi
+
+       # If systemd-pcrlock is missing then we need to use
+       # pcr-oracle.  For this we need to generate the RSA keys
+       # early.  Also we need to set the PCRs used to assest the
+       # system status
+       if [ "$arg_method" = "tpm2" ] || [ "$arg_method" = "tpm2+pin" ]; then
+               if [ -z "${FDE_SEAL_PCR_LIST}" ]; then
+                       if is_sdboot; then
+                               FDE_SEAL_PCR_LIST="0,2,4,7,9"
+                       elif is_grub2; then
+                               FDE_SEAL_PCR_LIST="0,2,4,7,8,9"
+                       else
+                               err "Bootloader not detected"
+                       fi
+               fi
+               [ -e /etc/sysconfig/fde-tools ] || echo 
"FDE_SEAL_PCR_LIST=${FDE_SEAL_PCR_LIST}" > /etc/sysconfig/fde-tools
+               # shellcheck disable=SC1091
+               . /etc/sysconfig/fde-tools
+
+               if ! have_pcrlock && have_pcr_oracle; then
+                       generate_rsa_key
+               fi
+
+               # During the initial enrollment it is expected that
+               # for systemd-pcrlock the recovery PIN will be
+               # extracted from the %u keyring "cryptenroll" entry
+               generate_tpm2_predictions
+       fi
+
+       # For the PIN (tpm2+pin) or password (password), we can get it
+       # from the %u keyring "pin" or "pw" entry, the PIN or PW
+       # environment variable, or introduced by the user
+       local pin_or_pw keyid
+       if [ "$arg_method" = "tpm2+pin" ]; then
+               keyid="$(keyctl id %user:pin 2> /dev/null)" || true
+               if [ -n "$keyid" ]; then
+                       pin_or_pw="$(keyctl pipe "$keyid")"
+               elif [ -n "$PIN" ]; then
+                       pin_or_pw="$PIN"
+               elif [ -n "$arg_ask_pin_or_pw" ]; then
+                       read -r -s -p "TPM2 PIN: " pin_or_pw
+               else
+                       err "Use %u:pin, PIN or --ask-pin to provide the TPM2 
PIN"
+               fi
+       elif [ "$arg_method" = "password" ]; then
+               local keyid
+               keyid="$(keyctl id %user:pw 2> /dev/null)" || true
+               if [ -n "$keyid" ]; then
+                       pin_or_pw="$(keyctl pipe "$keyid")"
+               elif [ -n "$PW" ]; then
+                       pin_or_pw="$PW"
+               elif [ -n "$arg_ask_pin_or_pw" ]; then
+                       read -r -s -p "Password: " pin_or_pw
+               else
+                       err "Use %u:pw, PW or --ask-pw to provide the password"
+               fi
+       fi
+
+       for dev in "${luks2_devices[@]}"; do
+               enroll_device "$dev" "$pin_or_pw"
+       done
+}
+
+unenroll_pcrlock()
+{
+       pcrlock remove-policy &> /dev/null || true
+       rm -fr /var/lib/pcrlock.d
+       rm -f /var/lib/systemd/pcrlock.json
+       rm -f "${boot_root}${boot_dst}/pcrlock.json"
+}
+
+unenroll_pcr_oracle()
+{
+       rm -f /etc/systemd/tpm2-pcr-private-key.pem
+       rm -f /etc/systemd/tpm2-pcr-public-key.pem
+       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"
+}
+
+unenroll_device()
+{
+       local dev="$1"
+
+       case "$arg_method" in
+               "tpm2"|"tpm2+pin")
+                       systemd-cryptenroll \
+                               --wipe-slot=tpm2 \
+                               "$dev"
+                       ;;
+
+               "fido2")
+                       systemd-cryptenroll \
+                               --wipe-slot=fido2 \
+                               "$dev"
+                       ;;
+
+               "password")
+                       systemd-cryptenroll \
+                               --wipe-slot=password \
+                               "$dev"
+                       ;;
+
+               *)
+                       err "Unexpected parameter for --method=: $arg_method"
+                       ;;
+       esac
+}
+
+unenroll()
+{
+       [ -e /etc/crypttab ] || { log_info "/etc/crypttab not found. No 
encrypted devices?"; return 0; }
+       [ -e /usr/bin/systemd-cryptenroll ] || { log_info "systemd-cryptenroll 
not found"; return 0; }
+       detect_luks2 || { log_info "No LUKS2 devices found"; return 0; }
+
+       # Prepare /etc/crypttab and update initrd if required
+       case "$arg_method" in
+               "tpm2"|"tpm2+pin")
+                       have_tpm2 || err "No TPM2 found found"
+                       remove_crypttab_option 'tpm2-device=auto'
+                       ;;
+
+               "fido2")
+                       have_fido2 || err "No FIDO2 key found"
+                       remove_crypttab_option 'fido2-device=auto'
+                       ;;
+       esac
+       if [ "$update_initrd" = "1" ]; then
+               arg_no_reuse_initrd=1
+               install_all_kernels "$root_snapshot"
+               # Avoid the call of generate_tpm2_predictions at the
+               # end of the script
+               update_predictions=
+       fi
+
+       # If systemd-pcrlock is missing then we need to use
+       # pcr-oracle.  For this we need to generate the RSA keys
+       # early.  Also we need to set the PCRs used to assest the
+       # system status
+       if [ "$arg_method" = "tpm2" ] || [ "$arg_method" = "tpm2+pin" ]; then
+               # Maybe we can remove fde-tools, but it is OK to keep
+               # it, as is a user configuration file
+               # [ ! -e /etc/sysconfig/fde-tools ] || rm 
/etc/sysconfig/fde-tools
+               unenroll_pcrlock
+               unenroll_pcr_oracle
+       fi
+
+       for dev in "${luks2_devices[@]}"; do
+               unenroll_device "$dev"
+       done
+}
+
 bootloader_name()
 {
        if is_sdboot "${1-$root_snapshot}"; then
@@ -2011,12 +2448,12 @@
 
 ####### main #######
 
-getopttmp=$(getopt -o hc:v --long 
help,flicker,verbose,esp-path:,entry-token:,arch:,image:,entry-keys:,no-variables,no-reuse-initrd,no-random-seed,ask-pin,all
 -n "${0##*/}" -- "$@")
+getopttmp=$(getopt -o hc:v --long 
help,flicker,verbose,esp-path:,entry-token:,arch:,image:,entry-keys:,no-variables,no-reuse-initrd,no-random-seed,all,portable,only-default,ask-pin,ask-pw,method:,signed-policy
 -n "${0##*/}" -- "$@")
 eval set -- "$getopttmp"
 
 while true ; do
-        case "$1" in
-                -h|--help) helpandquit ;;
+       case "$1" in
+               -h|--help) helpandquit ;;
                --flicker) dialog_altenate_screen=--keep-tite; shift ;;
                -v|--verbose) verbose=$((++verbose)); shift ;;
                --esp-path) arg_esp_path="$2"; shift 2 ;;
@@ -2027,14 +2464,18 @@
                --no-variables) arg_no_variables=1; shift ;;
                --no-reuse-initrd) arg_no_reuse_initrd=1; shift ;;
                --no-random-seed) arg_no_random_seed=1; shift ;;
-               --ask-pin) arg_ask_pin=1; shift ;;
                --all) arg_all_entries=1; shift ;;
-                --) shift ; break ;;
-                *) echo "Internal error!" ; exit 1 ;;
-        esac
+               --portable) arg_portable=1; shift ;;
+               --only-default) arg_only_default=1; shift ;;
+               --ask-pin|--ask-pw) arg_ask_pin_or_pw=1; shift ;;
+               --method) arg_method="$2"; shift 2 ;;
+               --signed-policy) arg_signed_policy=1; shift ;;
+               --) shift ; break ;;
+               *) echo "Internal error!" ; exit 1 ;;
+       esac
 done
 
-if [ -z "$SYSTEMD_LOG_LEVEL" -a -n "$verbose" ]; then
+if [ -z "$SYSTEMD_LOG_LEVEL" ] && [ -n "$verbose" ]; then
        if [ "$verbose" -gt 1 ]; then
                SYSTEMD_LOG_LEVEL=debug
        else
@@ -2044,7 +2485,7 @@
 fi
 
 case "$1" in
-       
install|needs-update|update|force-update|add-kernel|remove-kernel|set-default-snapshot|add-all-kernels|mkinitrd|remove-all-kernels|is-installed|list-snapshots|list-entries|list-kernels|show-entry|is-bootable|update-predictions|bootloader)
 ;;
+       
install|needs-update|update|force-update|add-kernel|remove-kernel|set-default-snapshot|add-all-kernels|mkinitrd|remove-all-kernels|is-installed|list-snapshots|list-entries|list-kernels|show-entry|is-bootable|enroll|unenroll|update-predictions|bootloader)
 ;;
        kernels|snapshots|entries|"") stty_size; interactive=1 ;;
        *) err "unknown command $1" ;;
 esac
@@ -2052,6 +2493,7 @@
 [ -n "$arg_esp_path" ] && export SYSTEMD_ESP_PATH="$arg_esp_path"
 
 # XXX: bootctl should have json output for that too
+# shellcheck disable=SC2016
 eval "$(bootctl 2>/dev/null | sed -ne 's/Firmware Arch: 
*\(\w\+\)/firmware_arch="\1"/p;s/ *token: *\(\w\+\)/entry_token="\1"/p;s, 
*\$BOOT: *\([^ ]\+\).*,boot_root="\1",p')"
 read -r root_uuid root_device < <(findmnt / -v -r -n -o UUID,SOURCE)
 root_subvol=""
@@ -2084,7 +2526,13 @@
 esac
 
 # XXX: Unify both in /EFI/opensuse?
-if is_sdboot; then
+if [ -n "$arg_portable" ]; then
+       if [ ! -d "$boot_root/EFI/systemd" ] && [ ! -d 
"$boot_root/EFI/opensuse" ]; then
+               boot_dst="/EFI/BOOT"
+       else
+               err "Bootloader is already installed permanently"
+       fi
+elif is_sdboot; then
        boot_dst="/EFI/systemd"
 elif is_grub2; then
        boot_dst="/EFI/opensuse"
@@ -2139,6 +2587,10 @@
        show_entry_fields "${3:-$root_snapshot}" "$2"
 elif [ "$1" = "is-bootable" ]; then
        is_bootable "${2:-$root_snapshot}"
+elif [ "$1" = "enroll" ]; then
+       enroll
+elif [ "$1" = "unenroll" ]; then
+       unenroll
 elif [ "$1" = "update-predictions" ]; then
        update_predictions=1
 elif [ "$1" = "kernels" ]; then

++++++ sdbootutil.obsinfo ++++++
--- /var/tmp/diff_new_pack.KMOSfE/_old  2024-07-18 19:15:20.144717915 +0200
+++ /var/tmp/diff_new_pack.KMOSfE/_new  2024-07-18 19:15:20.144717915 +0200
@@ -1,5 +1,5 @@
 name: sdbootutil
-version: 1+git20240704.a2c5a26
-mtime: 1720094445
-commit: a2c5a26866076afd91446dea57a44ac91746a4bf
+version: 1+git20240718.6fbaad1
+mtime: 1721296961
+commit: 6fbaad1a48cb99629775d6584cdbc90de826a1d8
 

Reply via email to