mirror of
https://github.com/linuxboot/heads.git
synced 2024-12-18 20:47:55 +00:00
f43fe1a836
- fi misplaced - rework reencryption loop - added verbose output on TPM DUK key addition when LUKS container can be unlocked with DRK Current state, left todo for future work: TPM DUK: - TPM DUK setup on defautl boot reuses /boot/kexec_key_devices.txt if present - If not, list all LUKS partitions, asks user for selection and makes sure LUKS passphrase can unlock all - Works on both LUKSv1 and LUKSv2 containers, reusing OS installer settings (Heads doesn't enforce better then OS installer LUKS parameters) LUKS passphrase change/LUKS reencryption: - Reuses /boot/kexec_key_devices.txt if existing - If not, prompts for LUKS passphase, list all LUKS containers not being USB based and attempt to unlock all those, listing only the ones successfully unlocked - Prompts user to reuse found unlockable LUKS partitions with LUKS passphrase, caches and reuse in other LUKS operations (passphrase change as well from oem factory reset/re-ownership) - Deals properly with LUKSv1/LUKSv2/multiple LUKS containers and reencrypt/passphrase changes them all if accepted, otherwise asks user to select individual LUKS container Tested on luksv1,luksv2, btrfs under luks (2x containers) and TPM DUK setup up to booting OS. All good TODO: - LUKS passphrase check is done multiple times across TPM DUK, reencryption and luks passphrase. Could refactor to change this, but since this op is done only one reencrypt+passphrase change) upon hardare reception from OEM, I stopped caring here. Signed-off-by: Thierry Laurion <insurgo@riseup.net>
584 lines
24 KiB
Bash
584 lines
24 KiB
Bash
#!/bin/bash
|
|
# This script contains various functions related to LUKS (Linux Unified Key Setup) encryption management.
|
|
|
|
. /etc/functions
|
|
. /etc/gui_functions
|
|
. /tmp/config
|
|
|
|
# List all LUKS devices on the system that are not USB
|
|
list_local_luks_devices() {
|
|
TRACE_FUNC
|
|
lvm vgscan || true
|
|
blkid | cut -d ':' -f 1 | while read -r device; do
|
|
DEBUG "Checking device: $device"
|
|
if cryptsetup isLuks "$device"; then
|
|
DEBUG "Device $device is a LUKS device"
|
|
dev_name=$(basename "$device")
|
|
parent_dev_name=$(echo "$dev_name" | sed 's/[0-9]*$//')
|
|
if [ -e "/sys/block/$parent_dev_name" ]; then
|
|
DEBUG "Device $device exists in /sys/block"
|
|
if ! stat -c %N "/sys/block/$parent_dev_name" 2>/dev/null | grep -q "usb"; then
|
|
DEBUG "Device $device is not a USB device"
|
|
echo "$device"
|
|
else
|
|
DEBUG "Device $device is a USB device, skipping"
|
|
fi
|
|
else
|
|
DEBUG "Device $device does not exist in /sys/block, skipping"
|
|
fi
|
|
else
|
|
DEBUG "Device $device is not a LUKS device"
|
|
fi
|
|
done | sort
|
|
}
|
|
|
|
# Prompt for LUKS Disk Recovery Key passphrase
|
|
prompt_luks_passphrase() {
|
|
TRACE_FUNC
|
|
while [[ ${#luks_current_Disk_Recovery_Key_passphrase} -lt 8 ]]; do
|
|
echo -e "\nEnter the LUKS Disk Recovery Key passphrase (At least 8 characters long):"
|
|
read -r luks_current_Disk_Recovery_Key_passphrase
|
|
if [[ ${#luks_current_Disk_Recovery_Key_passphrase} -lt 8 ]]; then
|
|
echo -e "\nPassphrase must be at least 8 characters long. Please try again."
|
|
unset luks_current_Disk_Recovery_Key_passphrase
|
|
continue
|
|
fi
|
|
done
|
|
echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/secret/luks_current_Disk_Recovery_Key_passphrase
|
|
}
|
|
|
|
# Test LUKS passphrase against all found LUKS containers that are not USB
|
|
test_luks_passphrase() {
|
|
TRACE_FUNC
|
|
|
|
list_local_luks_devices >/tmp/luks_devices.txt
|
|
if [ ! -s /tmp/luks_devices.txt ]; then
|
|
warn "No LUKS devices found"
|
|
return 1
|
|
fi
|
|
|
|
valid_luks_devices=()
|
|
while read -r luks_device; do
|
|
DEBUG "Testing passphrase on $luks_device"
|
|
if cryptsetup open --test-passphrase "$luks_device" --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase; then
|
|
DEBUG "Passphrase valid for $luks_device"
|
|
valid_luks_devices+=("$luks_device")
|
|
else
|
|
DEBUG "Passphrase test failed on $luks_device"
|
|
fi
|
|
done </tmp/luks_devices.txt
|
|
|
|
if [ ${#valid_luks_devices[@]} -eq 0 ]; then
|
|
return 1
|
|
fi
|
|
|
|
# Export the valid LUKS devices
|
|
export LUKS="${valid_luks_devices[*]}"
|
|
return 0
|
|
}
|
|
|
|
# Confirm with the user to use all unlockable LUKS partitions
|
|
confirm_luks_partitions() {
|
|
TRACE_FUNC
|
|
MSG="The following LUKS partitions can be unlocked:\n\n${LUKS}\n\nDo you want to use all of these partitions?"
|
|
if [ -x /bin/whiptail ]; then
|
|
if ! whiptail --title "Confirm LUKS Partitions" --yesno "$MSG" 0 80; then
|
|
die "User aborted the operation"
|
|
fi
|
|
else
|
|
echo -e "$MSG"
|
|
read -p "Do you want to use all of these partitions? (y/n): " confirm
|
|
if [ "$confirm" != "y" ]; then
|
|
die "User aborted the operation"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Main function to prompt for passphrase, test it, and confirm partitions
|
|
main_luks_selection() {
|
|
TRACE_FUNC
|
|
prompt_luks_passphrase
|
|
if ! test_luks_passphrase; then
|
|
die "Passphrase test failed on all LUKS devices"
|
|
fi
|
|
confirm_luks_partitions
|
|
DEBUG "Selected LUKS partitions: $LUKS"
|
|
}
|
|
|
|
#Whiptail prompt asking user to select ratio of device to use for LUKS container between: 25, 50, 75
|
|
select_luks_container_size_percent() {
|
|
TRACE_FUNC
|
|
if [ -x /bin/whiptail ]; then
|
|
#whiptail prompt asking user to select ratio of device to use for LUKS container between: 25, 50, 75
|
|
#whiptail returns the percentage of the device to use for LUKS container
|
|
whiptail --title "Select LUKS container size percentage of device" --menu \
|
|
"Select LUKS container size percentage of device:" 0 80 10 \
|
|
"10" "10%" \
|
|
"25" "25%" \
|
|
"50" "50%" \
|
|
"75" "75%" \
|
|
2> /tmp/luks_container_size_percent \
|
|
|| die "Error selecting LUKS container size percentage of device"
|
|
else
|
|
#console prompt asking user to select ratio of device to use for LUKS container between: 10, 25, 50, 75
|
|
#console prompt returns the percentage of the device to use for LUKS container
|
|
echo "Select LUKS container size percentage of device:"
|
|
echo "1. 10%"
|
|
echo "2. 25%"
|
|
echo "3. 50%"
|
|
echo "4. 75%"
|
|
read -p "Choose your LUKS container size percentage of device [1-3]: " option_index
|
|
if [ "$option_index" = "1" ]; then
|
|
echo "10" >/tmp/luks_container_size_percent
|
|
elif [ "$option_index" = "2" ]; then
|
|
echo "25" >/tmp/luks_container_size_percent
|
|
elif [ "$option_index" = "3" ]; then
|
|
echo "50" >/tmp/luks_container_size_percent
|
|
elif [ "$option_index" = "4" ]; then
|
|
echo "75" >/tmp/luks_container_size_percent
|
|
else
|
|
die "Error selecting LUKS container size percentage of device"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Partition a device interactively with two partitions: a LUKS container
|
|
# containing private ext4 partition and second public exFAT partition
|
|
# Size provisioning is done by percentage of the device
|
|
interactive_prepare_thumb_drive() {
|
|
TRACE_FUNC
|
|
#Refactoring: only one parameter needed to be prompted for: the passphrase for LUKS container if not coming from oem-provisioning
|
|
#If no passphrase was provided, ask user to select passphrase for LUKS container
|
|
# if no device provided as parameter, we will ask user to select device to partition
|
|
# if no percentage provided as parameter, we will default to 10% of device to use for LUKS container
|
|
# we will validate parameters and not make them positional and print a usage function first
|
|
|
|
#Set defaults
|
|
DEVICE="" #Will list all usb storage devices if not provided as parameter
|
|
PERCENTAGE="10" #default to 10% of device to use for LUKS container (requires a LUKS partition bigger then 32mb!)
|
|
PASSPHRASE="" #Will prompt user for passphrase if not provided as parameter
|
|
|
|
#Parse parameters
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--device)
|
|
DEVICE=$2
|
|
shift 2
|
|
;;
|
|
--percentage)
|
|
PERCENTAGE=$2
|
|
shift 2
|
|
;;
|
|
--pass)
|
|
PASSPHRASE=$2
|
|
shift 2
|
|
;;
|
|
*)
|
|
echo "usage: prepare_thumb_drive [--device device] [--percentage percentage] [--pass passphrase]"
|
|
return 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
DEBUG "DEVICE to partition: $DEVICE"
|
|
DEBUG "PERCENTAGE of device that will be used for LUKS container: $PERCENTAGE"
|
|
#Output provided if passphrase is provided as parameter
|
|
DEBUG "PASSPHRASE for LUKS container: ${PASSPHRASE:+provided}"
|
|
|
|
#Prompt for passphrase if not provided as parameter
|
|
if [ -z "$PASSPHRASE" ]; then
|
|
#If no passphrase was provided, ask user to select passphrase for LUKS container
|
|
#console based no whiptail
|
|
while [[ ${#PASSPHRASE} -lt 8 ]]; do
|
|
{
|
|
echo -e "\nEnter passphrase for LUKS container (At least 8 characters long):"
|
|
#hide passphrase input from read command
|
|
read -r -s PASSPHRASE
|
|
#skip confirmation if passphrase is less then 8 characters long (continue)
|
|
if [[ ${#PASSPHRASE} -lt 8 ]]; then
|
|
echo -e "\nPassphrase must be at least 8 characters long. Please try again."
|
|
unset PASSPHRASE
|
|
continue
|
|
fi
|
|
#validate passphrase and ask user to re-enter if not at least 8 characters long
|
|
#confirm passphrase
|
|
echo -e "\nConfirm passphrase for LUKS container:"
|
|
#hide passphrase input from read command
|
|
read -r -s PASSPHRASE_CONFIRM
|
|
#compare passphrase and passphrase confirmation
|
|
if [ "$PASSPHRASE" != "$PASSPHRASE_CONFIRM" ]; then
|
|
echo -e "\nPassphrases do not match. Please try again."
|
|
unset PASSPHRASE
|
|
unset PASSPHRASE_CONFIRM
|
|
fi
|
|
|
|
}
|
|
done
|
|
fi
|
|
|
|
#If no device was provided, ask user to select device to partition
|
|
if [ -z "$DEVICE" ]; then
|
|
#warn user to disconnect all external drives
|
|
if [ -x /bin/whiptail ]; then
|
|
whiptail_warning --title "WARNING: Disconnect all external drives" --msgbox \
|
|
"WARNING: Please disconnect all external drives before proceeding.\n\nHit Enter to continue." 0 80 ||
|
|
die "User cancelled wiping and repartitioning of $DEVICE"
|
|
else
|
|
echo -e -n "Warning: Please disconnect all external drives before proceeding.\n\nHit Enter to continue?"
|
|
read -r -p " [Y/n] " response
|
|
#transform response to uppercase with bash parameter expansion
|
|
response=${response^^}
|
|
#continue if response different then uppercase N
|
|
if [[ $response =~ ^(N)$ ]]; then
|
|
die "User cancelled wiping and repartitioning of $DEVICE"
|
|
fi
|
|
fi
|
|
|
|
#enable usb
|
|
enable_usb
|
|
#enable usb storage
|
|
enable_usb_storage
|
|
|
|
#list all usb storage devices
|
|
list_usb_storage disks >/tmp/devices.txt
|
|
if [ $(cat /tmp/devices.txt | wc -l) -gt 0 ]; then
|
|
file_selector "/tmp/devices.txt" "Select device to partition"
|
|
if [ "$FILE" == "" ]; then
|
|
die "Error: No device selected"
|
|
else
|
|
DEVICE=$FILE
|
|
fi
|
|
else
|
|
die "Error: No device found"
|
|
fi
|
|
fi
|
|
|
|
#Check if device is a block device
|
|
if [ ! -b $DEVICE ]; then
|
|
die "Error: $DEVICE is not a block device"
|
|
fi
|
|
|
|
if [ -z "$PERCENTAGE" ]; then
|
|
#If no percentage was provided, ask user to select percentage of device to use for LUKS container
|
|
select_luks_container_size_percent
|
|
PERCENTAGE=$(cat /tmp/luks_container_size_percent)
|
|
fi
|
|
|
|
confirm_thumb_drive_format "$DEVICE" "$PERCENTAGE" ||
|
|
die "User cancelled wiping and repartitioning of $DEVICE"
|
|
|
|
prepare_thumb_drive "$DEVICE" "$PERCENTAGE" "$PASSPHRASE"
|
|
}
|
|
|
|
# Show a prompt to confirm formatting a flash drive with a percentage allocated
|
|
# to LUKS. interactive_prepare_thumb_drive() uses this; during OEM reset it is
|
|
# used separately before performing any reset actions
|
|
#
|
|
# parameters:
|
|
# $1 - block device of flash drive
|
|
# $2 - percent of device allocated to LUKS [1-99]
|
|
confirm_thumb_drive_format() {
|
|
TRACE_FUNC
|
|
local DEVICE LUKS_PERCENTAGE DISK_SIZE_BYTES DISK_SIZE_DISPLAY LUKS_PERCENTAGE LUKS_SIZE_MB MSG
|
|
|
|
DEVICE="$1"
|
|
LUKS_PERCENTAGE="$2"
|
|
|
|
LUKS_SIZE_MB=
|
|
|
|
#Get disk size in bytes
|
|
DISK_SIZE_BYTES="$(blockdev --getsize64 "$DEVICE")"
|
|
DISK_SIZE_DISPLAY="$(display_size "$DISK_SIZE_BYTES")"
|
|
#Convert disk size to MB
|
|
DISK_SIZE_MB=$((DISK_SIZE_BYTES/1024/1024))
|
|
#Calculate percentage of device in MB
|
|
LUKS_SIZE_MB="$((DISK_SIZE_BYTES*LUKS_PERCENTAGE/100/1024/1024))"
|
|
|
|
MSG="WARNING: Wiping and repartitioning $DEVICE ($DISK_SIZE_DISPLAY) with $LUKS_SIZE_MB MB\n assigned to private LUKS ext4 partition,\n rest assigned to exFAT public partition.\n\nAre you sure you want to continue?"
|
|
if [ -x /bin/whiptail ]; then
|
|
whiptail_warning --title "WARNING: Wiping and repartitioning $DEVICE ($DISK_SIZE_DISPLAY)" --yesno \
|
|
"$MSG" 0 80
|
|
else
|
|
echo -e -n "$MSG"
|
|
read -r -p " [Y/n] " response
|
|
#transform response to uppercase with bash parameter expansion
|
|
response=${response^^}
|
|
#continue if response is Y, y, or empty, abort for anything else
|
|
if [ -n "$response" ] && [ "${response^^}" != Y ]; then
|
|
return 1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Prepare a flash drive with a private LUKS-encrypted ext4 partition and a
|
|
# public exFAT partition. This is not interactive - during OEM reset, any
|
|
# selections/confirmations must occur before OEM reset starts resetting the
|
|
# system.
|
|
#
|
|
# $1 - block device of flash drive
|
|
# $2 - percentage of flash drive to allocate to LUKS [1-99]
|
|
# $3 - passphrase for LUKS container
|
|
prepare_thumb_drive() {
|
|
TRACE_FUNC
|
|
|
|
local DEVICE PERCENTAGE PASSPHRASE DISK_SIZE_BYTES PERCENTAGE_MB
|
|
DEVICE="$1"
|
|
PERCENTAGE="$2"
|
|
PASSPHRASE="$3"
|
|
|
|
#Get disk size in bytes
|
|
DISK_SIZE_BYTES="$(blockdev --getsize64 "$DEVICE")"
|
|
#Calculate percentage of device in MB
|
|
PERCENTAGE_MB="$((DISK_SIZE_BYTES*PERCENTAGE/100/1024/1024))"
|
|
|
|
echo -e "Preparing $DEVICE with $PERCENTAGE_MB MB for private LUKS container while rest of device will be assigned to exFAT public partition...\n"
|
|
echo "Please wait..."
|
|
DEBUG "Creating empty DOS partition table on device through fdisk to start clean"
|
|
echo -e "o\nw\n" | fdisk $DEVICE >/dev/null 2>&1 || die "Error creating partition table"
|
|
DEBUG "partition device with two partitions: first one being the percent applied and rest for second partition through fdisk"
|
|
echo -e "n\np\n1\n\n+"$PERCENTAGE_MB"M\nn\np\n2\n\n\nw\n" | fdisk $DEVICE >/dev/null 2>&1 || die "Error partitioning device"
|
|
DEBUG "cryptsetup luksFormat first partition with LUKS container aes-xts-plain64 cipher with sha256 hash and 512 bit key"
|
|
DEBUG "Creating ${PERCENTAGE_MB}MB LUKS container on ${DEVICE}1..."
|
|
DO_WITH_DEBUG cryptsetup --batch-mode -c aes-xts-plain64 -h sha256 -s 512 -y luksFormat ${DEVICE}1 \
|
|
--key-file <(echo -n "${PASSPHRASE}") > /dev/null 2>&1 \
|
|
|| die "Error formatting LUKS container"
|
|
DEBUG "Opening LUKS device and mapping under /dev/mapper/private..."
|
|
DO_WITH_DEBUG cryptsetup open ${DEVICE}1 private --key-file <(echo -n "${PASSPHRASE}") > /dev/null 2>&1 \
|
|
|| die "Error opening LUKS container"
|
|
DEBUG "Formatting LUKS container mapped under /dev/mapper/private as an ext4 partition..."
|
|
mke2fs -t ext4 -L private /dev/mapper/private >/dev/null 2>&1 || die "Error formatting LUKS container's ext4 filesystem"
|
|
DEBUG "Closing LUKS device /dev/mapper/private..."
|
|
cryptsetup close private > /dev/null 2>&1 || die "Error closing LUKS container"
|
|
DEBUG "Formatting second partition ${DEVICE}2 with exfat filesystem..."
|
|
mkfs.exfat -L public ${DEVICE}2 >/dev/null 2>&1 || die "Error formatting second partition with exfat filesystem"
|
|
echo "Done."
|
|
}
|
|
|
|
# Select LUKS container
|
|
select_luks_container() {
|
|
TRACE_FUNC
|
|
if [ -s /boot/kexec_key_devices.txt ]; then
|
|
DEBUG "Reusing known good LUKS container device from /boot/kexec_key_devices.txt"
|
|
LUKS=$(cut -d ' ' -f1 /boot/kexec_key_devices.txt)
|
|
DEBUG "LUKS container device: $(echo $LUKS)"
|
|
elif [ -z "$LUKS" ]; then
|
|
main_luks_selection
|
|
fi
|
|
}
|
|
|
|
# Test LUKS current disk recovery key passphrase
|
|
test_luks_current_disk_recovery_key_passphrase() {
|
|
TRACE_FUNC
|
|
while :; do
|
|
select_luks_container || return 1
|
|
|
|
PRINTABLE_LUKS=$(echo $LUKS)
|
|
|
|
if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ]; then
|
|
echo -e "\nEnter the current LUKS Disk Recovery Key passphrase (Configured at OS installation or by OEM):"
|
|
read -r luks_current_Disk_Recovery_Key_passphrase
|
|
echo -n "$luks_current_Disk_Recovery_Key_passphrase" > /tmp/secret/luks_current_Disk_Recovery_Key_passphrase
|
|
else
|
|
echo -n "$luks_current_Disk_Recovery_Key_passphrase" > /tmp/secret/luks_current_Disk_Recovery_Key_passphrase
|
|
fi
|
|
|
|
echo -e "\n$PRINTABLE_LUKS: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..."
|
|
|
|
for luks_container in $LUKS; do
|
|
DEBUG "$luks_container: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..."
|
|
if ! cryptsetup open --test-passphrase "$luks_container" --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase; then
|
|
whiptail_error --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \
|
|
"If you previously changed it and do not remember it, you will have to reinstall the OS from an external drive.\n\nTo do so, place the ISO file and its signature file on root of an external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80
|
|
detect_boot_device
|
|
mount -o remount,rw /boot
|
|
rm -f /boot/kexec_key_devices.txt
|
|
mount -o remount,ro /boot
|
|
luks_secrets_cleanup
|
|
unset LUKS
|
|
else
|
|
echo "$luks_container: unlocking LUKS container with current Disk Recovery Key passphrase successful"
|
|
export luks_current_Disk_Recovery_Key_passphrase
|
|
fi
|
|
done
|
|
|
|
if [ -n "$LUKS" ]; then
|
|
export LUKS
|
|
TRACE_FUNC
|
|
DEBUG "LUKS container(s) $PRINTABLE_LUKS exported to be reused"
|
|
break
|
|
fi
|
|
done
|
|
}
|
|
|
|
# Function to re-encrypt LUKS partitions
|
|
luks_reencrypt() {
|
|
TRACE_FUNC
|
|
test_luks_current_disk_recovery_key_passphrase || return 1
|
|
|
|
luks_containers=($LUKS)
|
|
TRACE_FUNC
|
|
DEBUG "luks_containers: ${luks_containers[@]}"
|
|
|
|
if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ]; then
|
|
if [ -f /tmp/secret/luks_current_Disk_Recovery_Key_passphrase ]; then
|
|
luks_current_Disk_Recovery_Key_passphrase=$(cat /tmp/secret/luks_current_Disk_Recovery_Key_passphrase)
|
|
else
|
|
msg=$(echo -e "This will replace the encrypted container content and its LUKS Disk Recovery Key.\n\nThe passphrase associated with this key will be asked from the user under the following conditions:\n 1-Every boot if no Disk Unlock Key was added to the TPM\n 2-If the TPM fails (hardware failure)\n 3-If the firmware has been tampered with/modified by the user\n\nThis process requires you to type the current LUKS Disk Recovery Key passphrase and will delete the LUKS TPM Disk Unlock Key slot, if set up, by setting a default boot LUKS key slot (1) if present.\n\nAt the next prompt, you may be asked to select which file corresponds to the LUKS device container.\n\nHit Enter to continue." | fold -w 70 -s)
|
|
whiptail --title 'Reencrypt LUKS encrypted container ?' --msgbox "$msg" 0 80
|
|
echo -e "\nEnter the current LUKS Disk Recovery Key passphrase:"
|
|
read -r -s luks_current_Disk_Recovery_Key_passphrase
|
|
echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/secret/luks_current_Disk_Recovery_Key_passphrase
|
|
fi
|
|
else
|
|
echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/secret/luks_current_Disk_Recovery_Key_passphrase
|
|
fi
|
|
|
|
for luks_container in "${luks_containers[@]}"; do
|
|
DEBUG "$luks_container: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..."
|
|
if ! DO_WITH_DEBUG cryptsetup open --test-passphrase "$luks_container" --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase >/dev/null 2>&1; then
|
|
whiptail_error --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \
|
|
"If you previously changed it and do not remember it, you will have to reinstall the OS from an external drive.\n\nTo do so, place the ISO file and its signature file on root of an external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80
|
|
TRACE_FUNC
|
|
detect_boot_device
|
|
mount -o remount,rw /boot
|
|
rm -f /boot/kexec_key_devices.txt
|
|
mount -o remount,ro /boot
|
|
luks_secrets_cleanup
|
|
unset LUKS
|
|
continue
|
|
fi
|
|
|
|
DEBUG "Test opening ${luks_container} successful. Now testing key slots to determine which holds master key"
|
|
DRK_KEYSLOT=-1
|
|
DEBUG "$luks_container: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..."
|
|
for i in $(seq 0 31); do
|
|
DEBUG "Testing key slot $i on $luks_container"
|
|
if DO_WITH_DEBUG cryptsetup open --test-passphrase $luks_container --key-slot $i --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase >/dev/null 2>&1; then
|
|
DRK_KEYSLOT=$i
|
|
DEBUG "$luks_container: Found key-slot $DRK_KEYSLOT that can be unlocked with the current passphrase. breaking loop"
|
|
break
|
|
else
|
|
DEBUG "Key slot $i on $luks_container cannot be unlocked with the current passphrase"
|
|
fi
|
|
done
|
|
|
|
if [ $DRK_KEYSLOT -eq -1 ]; then
|
|
whiptail_error --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \
|
|
"If you previously changed it and do not remember it, you will have to reinstall the OS from an external drive.\n\nTo do so, place the ISO file and its signature file on root of an external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80
|
|
TRACE_FUNC
|
|
detect_boot_device
|
|
mount -o remount,rw /boot
|
|
rm -f /boot/kexec_key_devices.txt
|
|
mount -o remount,ro /boot
|
|
luks_secrets_cleanup
|
|
unset LUKS
|
|
continue
|
|
fi
|
|
|
|
# --perf-no_read_workqueue and/or --perf-no_write_workqueue improve encryption/reencrypton performance on kernel 5.10.9+
|
|
# bypassing dm-crypt queues.
|
|
# Ref https://github.com/cloudflare/linux/issues/1#issuecomment-729695518
|
|
# --resilience=none disables the resilience feature of cryptsetup, which is enabled by default
|
|
# --force-offline-reencrypt forces the reencryption to be done offline (no read/write operations on the device)
|
|
# --disable-locks disables the lock feature of cryptsetup, which is enabled by default
|
|
|
|
echo -e "\nReencrypting $luks_container LUKS encrypted drive content with current Recovery Disk Key passphrase..."
|
|
warn "DO NOT POWER DOWN MACHINE, UNPLUG AC OR REMOVE BATTERY DURING REENCRYPTION PROCESS"
|
|
|
|
if ! DO_WITH_DEBUG cryptsetup reencrypt \
|
|
--perf-no_read_workqueue --perf-no_write_workqueue \
|
|
--resilience=none --force-offline-reencrypt --disable-locks \
|
|
"$luks_container" --key-slot "$DRK_KEYSLOT" \
|
|
--key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase; then
|
|
whiptail_error --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \
|
|
"If you previously changed it and do not remember it, you will have to reinstall the OS from an external drive.\n\nTo do so, place the ISO file and its signature file on root of an external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80
|
|
TRACE_FUNC
|
|
detect_boot_device
|
|
mount -o remount,rw /boot
|
|
rm -f /boot/kexec_key_devices.txt
|
|
mount -o remount,ro /boot
|
|
luks_secrets_cleanup
|
|
unset LUKS
|
|
else
|
|
export luks_current_Disk_Recovery_Key_passphrase
|
|
export LUKS
|
|
fi
|
|
done
|
|
}
|
|
|
|
# Function to change LUKS passphrase
|
|
luks_change_passphrase() {
|
|
TRACE_FUNC
|
|
test_luks_current_disk_recovery_key_passphrase || return 1
|
|
|
|
luks_containers=($LUKS)
|
|
TRACE_FUNC
|
|
DEBUG "luks_containers: ${luks_containers[@]}"
|
|
|
|
for luks_container in "${luks_containers[@]}"; do
|
|
if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ] || [ -z "$luks_new_Disk_Recovery_Key_passphrase" ]; then
|
|
if [ -f /tmp/secret/luks_current_Disk_Recovery_Key_passphrase ]; then
|
|
luks_current_Disk_Recovery_Key_passphrase=$(cat /tmp/secret/luks_current_Disk_Recovery_Key_passphrase)
|
|
else
|
|
whiptail --title 'Changing LUKS Disk Recovery Key passphrase' --msgbox \
|
|
"Please enter the current LUKS Disk Recovery Key passphrase (slot 0).\nThen choose a strong passphrase of your own.\n\n**DICEWARE passphrase methodology is STRONGLY ADVISED.**\n\nHit Enter to continue" 0 80
|
|
|
|
echo -e "\nEnter your desired replacement for the actual LUKS Disk Recovery Key passphrase (At least 8 characters long):"
|
|
while [[ ${#luks_new_Disk_Recovery_Key_passphrase} -lt 8 ]]; do
|
|
read -r luks_new_Disk_Recovery_Key_passphrase
|
|
done
|
|
|
|
TRACE_FUNC
|
|
echo -e "\nEnter the current LUKS Disk Recovery Key passphrase (Configured at OS installation or by OEM):"
|
|
read -r luks_current_Disk_Recovery_Key_passphrase
|
|
fi
|
|
fi
|
|
|
|
echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/secret/luks_current_Disk_Recovery_Key_passphrase
|
|
echo -n "$luks_new_Disk_Recovery_Key_passphrase" >/tmp/secret/luks_new_Disk_Recovery_Key_passphrase
|
|
|
|
DEBUG "$luks_container: Test unlocking of LUKS encrypted drive content with current LUKS Disk Recovery Key passphrase..."
|
|
if ! DO_WITH_DEBUG cryptsetup open --test-passphrase "$luks_container" --key-file /tmp/secret/luks_current_Disk_Recovery_Key_passphrase >/dev/null 2>&1; then
|
|
whiptail_error --title "$luks_container: Wrong current LUKS Disk Recovery Key passphrase?" --msgbox \
|
|
"If you previously changed it and do not remember it, you will have to reinstall the OS from an external drive.\n\nTo do so, place the ISO file and its signature file on root of an external drive, and select Options-> Boot from USB \n\nHit Enter to retry." 0 80
|
|
TRACE_FUNC
|
|
detect_boot_device
|
|
mount -o remount,rw /boot
|
|
rm -f /boot/kexec_key_devices.txt
|
|
mount -o remount,ro /boot
|
|
luks_secrets_cleanup
|
|
unset LUKS
|
|
continue
|
|
fi
|
|
|
|
echo -e "\nChanging $luks_container LUKS encrypted disk passphrase to the new LUKS Disk Recovery Key passphrase..."
|
|
if ! DO_WITH_DEBUG cryptsetup luksChangeKey "$luks_container" --key-file=/tmp/secret/luks_current_Disk_Recovery_Key_passphrase /tmp/secret/luks_new_Disk_Recovery_Key_passphrase; then
|
|
whiptail_error --title 'Failed to change LUKS passphrase' --msgbox \
|
|
"Failed to change the passphrase for $luks_container.\nPlease try again." 0 80
|
|
continue
|
|
fi
|
|
|
|
echo "Success changing passphrase for $luks_container."
|
|
done
|
|
|
|
# Export the new passphrase if all containers were processed successfully
|
|
luks_current_Disk_Recovery_Key_passphrase=$luks_new_Disk_Recovery_Key_passphrase
|
|
export luks_current_Disk_Recovery_Key_passphrase
|
|
export luks_new_Disk_Recovery_Key_passphrase
|
|
export LUKS
|
|
}
|
|
|
|
# Cleanup LUKS secrets
|
|
luks_secrets_cleanup() {
|
|
TRACE_FUNC
|
|
|
|
#Cleanup
|
|
shred -n 10 -z -u /tmp/secret/luks_new_Disk_Recovery_Key_passphrase 2>/dev/null || true
|
|
shred -n 10 -z -u /tmp/secret/luks_current_Disk_Recovery_Key_passphrase 2>/dev/null || true
|
|
|
|
#Unset variables (when in same boot)
|
|
unset luks_current_Disk_Recovery_Key_passphrase
|
|
unset luks_new_Disk_Recovery_Key_passphrase
|
|
unset LUKS
|
|
}
|