From b47445c990e0b04f8fe4fceaa6be8bebc99e5e58 Mon Sep 17 00:00:00 2001 From: Alex Simkin Date: Wed, 22 Oct 2025 22:16:55 +0300 Subject: [PATCH] add CRYPTROOT_AUTOUNLOCK option and fix CRYPTROOT for uefi builds fixes #6280 --- extensions/fs-cryptroot-support.sh | 17 +++++++++++++---- extensions/grub.sh | 12 +++++++++++- lib/functions/configuration/main-config.sh | 4 ++-- lib/functions/image/initrd.sh | 1 + lib/functions/image/partitioning.sh | 12 +++++++++++- .../usr/lib/armbian/armbian-resize-filesystem | 7 ++++++- 6 files changed, 44 insertions(+), 9 deletions(-) diff --git a/extensions/fs-cryptroot-support.sh b/extensions/fs-cryptroot-support.sh index e2259e54ce..0d5f619a67 100644 --- a/extensions/fs-cryptroot-support.sh +++ b/extensions/fs-cryptroot-support.sh @@ -24,9 +24,18 @@ function extension_prepare_config__prepare_cryptroot() { function prepare_root_device__250_encrypt_root_device() { # We encrypt the rootdevice (currently a loop device) and return the new mapped rootdevice check_loop_device "$rootdevice" - display_alert "Extension: ${EXTENSION}: Encrypting root partition with LUKS..." "cryptsetup luksFormat $rootdevice" "" - echo -n $CRYPTROOT_PASSPHRASE | cryptsetup luksFormat $CRYPTROOT_PARAMETERS $rootdevice - - echo -n $CRYPTROOT_PASSPHRASE | cryptsetup luksOpen $rootdevice $CRYPTROOT_MAPPER - + display_alert "Extension: ${EXTENSION}: Encrypting root partition with LUKS..." "cryptsetup luksFormat $CRYPTROOT_PARAMETERS $rootdevice" "" + if [[ $CRYPTROOT_AUTOUNLOCK == "yes" ]]; then + display_alert "Extension: ${EXTENSION}: configuring LUKS autounlock" "" + declare -g cryptroot_autounlock_key_file=$(mktemp) + openssl rand -base64 32 > "$cryptroot_autounlock_key_file" + cryptsetup luksFormat $CRYPTROOT_PARAMETERS "$rootdevice" "$cryptroot_autounlock_key_file" + cryptsetup luksOpen --key-file "$cryptroot_autounlock_key_file" "$rootdevice" $CRYPTROOT_MAPPER + else # CRYPTROOT_PASSPHRASE case + display_alert "Extension: ${EXTENSION}: configuring LUKS password" "" + echo -n $CRYPTROOT_PASSPHRASE | cryptsetup luksFormat $CRYPTROOT_PARAMETERS $rootdevice - + echo -n $CRYPTROOT_PASSPHRASE | cryptsetup luksOpen $rootdevice $CRYPTROOT_MAPPER - + fi add_cleanup_handler cleanup_cryptroot display_alert "Extension: ${EXTENSION}: Root partition encryption complete." "" "ext" # TODO: pass /dev/mapper to Docker @@ -90,4 +99,4 @@ function post_umount_final_image__750_cryptroot_cleanup(){ function cleanup_cryptroot(){ cryptsetup luksClose "${CRYPTROOT_MAPPER}" 2>&1 display_alert "Cryptroot closed ${CRYPTROOT_MAPPER}" "${EXTENSION}" "info" -} \ No newline at end of file +} diff --git a/extensions/grub.sh b/extensions/grub.sh index b962c3aad3..28ad270d5b 100644 --- a/extensions/grub.sh +++ b/extensions/grub.sh @@ -21,6 +21,9 @@ function extension_prepare_config__prepare_grub_standard() { declare -g IMAGE_PARTITION_TABLE="gpt" # GPT partition table is essential for many UEFI-like implementations, eg Apple+Intel stuff. declare -g UEFISIZE=260 # in MiB - grub EFI is tiny - but some EFI BIOSes ignore small too small EFI partitions declare -g BOOTSIZE=0 # No separate /boot when using UEFI. + if [[ $BOOTPART_REQUIRED == "yes" ]]; then # It is important to place this into /boot to have unified boot partition, especially when CRYPTROOT is used + declare -g UEFI_MOUNT_POINT=/boot + fi declare -g EXTRA_BSP_NAME="${EXTRA_BSP_NAME}-grub" # Unique bsp name. declare -g UEFI_GRUB_TARGET_BIOS="" # Target for BIOS GRUB install, set to i386-pc when UEFI_ENABLE_BIOS_AMD64=yes and target is amd64 @@ -162,7 +165,7 @@ pre_umount_final_image__install_grub() { } fi - local install_grub_cmdline="grub-install --target=${UEFI_GRUB_TARGET} --no-nvram --removable" # nvram is global to the host, even across chroot. take care. + local install_grub_cmdline="grub-install --target=${UEFI_GRUB_TARGET} --efi-directory=${UEFI_MOUNT_POINT} --no-nvram --removable" # nvram is global to the host, even across chroot. take care. display_alert "Extension: ${EXTENSION}: Installing GRUB EFI..." "${UEFI_GRUB_TARGET}" "" chroot_custom "$chroot_target" "$install_grub_cmdline" || { exit_with_error "${install_grub_cmdline} failed!" @@ -174,7 +177,12 @@ pre_umount_final_image__install_grub() { # Irony: let's use grub-probe to find out the UUID of the root partition, and then create a symlink to it. # Another: on some systems (eg, not Docker) the thing might already exist due to udev actually working. # shellcheck disable=SC2016 # some wierd escaping going on there. + # Root is needed so that UUID of the unlocked /dev/mapper/armbian-root is discovered by grub-update, + # UUID is then put into grub.cfg instead of raw /dev/mapper/armbian-root which will fail further sanity check chroot_custom "$chroot_target" mkdir -pv '/dev/disk/by-uuid/"$(grub-probe --target=fs_uuid /)"' "||" true + # Include /boot that might point to a separate boot partition in case one exists (lvm, cryptroot) + # Even if boot partition doesn't exist - the command will be the same as mkdir for / above + chroot_custom "$chroot_target" mkdir -pv '/dev/disk/by-uuid/"$(grub-probe --target=fs_uuid /boot)"' "||" true display_alert "Extension: ${EXTENSION}: Creating GRUB config..." "grub-mkconfig" "" chroot_custom "$chroot_target" update-grub || { @@ -285,6 +293,8 @@ configure_grub() { GRUB_DISABLE_OS_PROBER=false # Have to be explicit about enabling os-prober GRUB_FONT="/usr/share/grub/unicode.pf2" # Be explicit about the font to use so Ubuntu does not freak out and mess gfxterm GRUB_GFXPAYLOAD=keep + GRUB_DISABLE_UUID=false # Be explicit about wanting UUID + GRUB_DISABLE_LINUX_UUID=false # Be explicit about wanting UUID grubCfgFrag if [[ "a${UEFI_GRUB_DISABLE_OS_PROBER}" != "a" ]]; then diff --git a/lib/functions/configuration/main-config.sh b/lib/functions/configuration/main-config.sh index 878bf57089..8db608135f 100644 --- a/lib/functions/configuration/main-config.sh +++ b/lib/functions/configuration/main-config.sh @@ -169,8 +169,8 @@ function do_main_configuration() { # Support for LUKS / cryptroot if [[ $CRYPTROOT_ENABLE == yes ]]; then enable_extension "fs-cryptroot-support" # add the tooling needed, cryptsetup - if [[ -z $CRYPTROOT_PASSPHRASE ]]; then # a passphrase is mandatory if rootfs encryption is enabled - exit_with_error "Root encryption is enabled but CRYPTROOT_PASSPHRASE is not set" + if [[ -z $CRYPTROOT_PASSPHRASE ]] && [[ -z $CRYPTROOT_AUTOUNLOCK ]]; then # a passphrase is mandatory if rootfs encryption is enabled, unless CRYPTROOT_AUTOUNLOCK is wanted + exit_with_error "Root encryption is enabled but CRYPTROOT_PASSPHRASE or CRYPTROOT_AUTOUNLOCK is not set" fi [[ -z $CRYPTROOT_MAPPER ]] && CRYPTROOT_MAPPER="armbian-root" # TODO: fixed name can't be used for parallel image building (rpardini: ?) [[ -z $CRYPTROOT_SSH_UNLOCK ]] && CRYPTROOT_SSH_UNLOCK=yes diff --git a/lib/functions/image/initrd.sh b/lib/functions/image/initrd.sh index 476ae84173..eaea5d121f 100644 --- a/lib/functions/image/initrd.sh +++ b/lib/functions/image/initrd.sh @@ -62,6 +62,7 @@ update_initramfs() { [[ -d "${chroot_target}/etc/dropbear-initramfs/" ]] && initrd_files_to_hash+=("${chroot_target}/etc/dropbear-initramfs/") [[ -d "${chroot_target}/etc/dropbear/initramfs/" ]] && initrd_files_to_hash+=("${chroot_target}/etc/dropbear/initramfs/") fi + initrd_files_to_hash+=("${chroot_target}/etc/crypttab") # for updates to rootdev UUID fi # Find all the affected files; parallel md5sum sum them; invert hash and path, and remove chroot prefix. diff --git a/lib/functions/image/partitioning.sh b/lib/functions/image/partitioning.sh index 1914b39607..c93172440e 100644 --- a/lib/functions/image/partitioning.sh +++ b/lib/functions/image/partitioning.sh @@ -324,9 +324,19 @@ function prepare_partitions() { # create fstab (and crypttab) entry if [[ $CRYPTROOT_ENABLE == yes ]]; then + luks_key_file="none" + if [[ $CRYPTROOT_AUTOUNLOCK == yes ]]; then + luks_key_file="/etc/rootfs.key" + display_alert "Saving rootfs.key and configuration for autounlock" "(location=${luks_key_file})" + mv ${cryptroot_autounlock_key_file:?} ${SDCARD}${luks_key_file} + mkdir -p $SDCARD/etc/initramfs-tools/conf.d/ + echo "UMASK=0077" > $SDCARD/etc/initramfs-tools/conf.d/key-umask.conf + echo "" >> $SDCARD/etc/cryptsetup-initramfs/conf-hook + echo "KEYFILE_PATTERN=${luks_key_file}" >> $SDCARD/etc/cryptsetup-initramfs/conf-hook + fi # map the LUKS container partition via its UUID to be the 'cryptroot' device physical_root_part_uuid="$(blkid -s UUID -o value $physical_rootdevice)" - echo "$CRYPTROOT_MAPPER UUID=${physical_root_part_uuid} none luks" >> $SDCARD/etc/crypttab + echo "$CRYPTROOT_MAPPER UUID=${physical_root_part_uuid} ${luks_key_file} luks" >> $SDCARD/etc/crypttab run_host_command_logged cat $SDCARD/etc/crypttab fi diff --git a/packages/bsp/common/usr/lib/armbian/armbian-resize-filesystem b/packages/bsp/common/usr/lib/armbian/armbian-resize-filesystem index 88b2ca12b5..70e7eba59d 100755 --- a/packages/bsp/common/usr/lib/armbian/armbian-resize-filesystem +++ b/packages/bsp/common/usr/lib/armbian/armbian-resize-filesystem @@ -189,7 +189,12 @@ do_resize_crypt() # It's probably no need to run 'cryptsetup resize'. # After reboot, it will auto resize to adapte the partition # 'cryptsetup resize' requires passphrase, so it will fail. - cryptsetup resize $name + # if /etc/rootfs.key is present - it can be done unattended + if [ -f /etc/rootfs.key ]; then + cryptsetup resize --key-file /etc/rootfs.key "$name" + else + cryptsetup resize "$name" + fi local parentsize=$(lsblk -n -b -o SIZE $parentdev | head -1)