Use cryptsetup --link-vk-to-keyring to save volume keys

Resolves: https://issues.redhat.com/browse/RHEL-104940
Conflict: None

commit 0d39f4fd626fea070d9b8af624feacd89938e7db
Author: Coiby Xu <coxu@redhat.com>
Date:   Wed Jun 18 09:16:26 2025 +0800

    Use cryptsetup --link-vk-to-keyring to save volume keys

    cryptsetup open --link-vk-to-keyring (man cryptsetup-open) will link
    volume key to specified keyring after successfully unlocking the volume.
    Use this feature to save key to @u::%logon:cryptsetup:$UUID to support
    the following cases
    - volume is unlocked automatically say using TPM-sealed key
    - ask user to input passphrase to unlock the volume

    Signed-off-by: Coiby Xu <coxu@redhat.com>

Signed-off-by: Coiby Xu <coxu@redhat.com>
This commit is contained in:
Coiby Xu 2025-10-09 16:49:53 +08:00
parent 748b3c3ee0
commit 557335e8a1

View File

@ -1057,9 +1057,42 @@ check_final_action_config()
fi
}
_get_luks_key_by_unlock()
{
local _devuuid=$1 _key_des=$2
local _max_retries
local _attempt=1
local _luks_unlock_cmd=""
# Check if stdin is a terminal.
if [ -t 0 ]; then
_max_retries=5
ddebug "Attempting to unlock LUKS device. You have $_max_retries attempts."
else
# Not a terminal (e.g., running as system service), so only try once
# for cases where volume key is sealed to TPM which doesn't need user
# interaction.
_max_retries=1
ddebug "Attempting to unlock LUKS device (non-interactive mode)..."
fi
while [ "$_attempt" -le "$_max_retries" ]; do
if cryptsetup open "UUID=$_devuuid" DUMMY "--link-vk-to-keyring=@u::%logon:$_key_des" --test-passphrase; then
ddebug "Success: LUKS device unlocked."
dwarn "To avoid manually running kdumpctl, ensure the link-volume-key=@u::%logon:$_key_des option is correctly set up in /etc/crypttab (see man crypttab)."
return 0
fi
_attempt=$((_attempt + 1))
done
derror "Error: Could not unlock the LUKS device."
return 1
}
prepare_luks()
{
local _luks_dev _key_id _key_des
local _luks_dev _key_id _key_des _luks_unlock_cmd
declare -a _luks_devs
mapfile -t _luks_devs < <(get_all_kdump_crypt_dev)
@ -1078,12 +1111,19 @@ prepare_luks()
_key_dir=$LUKS_CONFIGFS/$_devuuid
_key_des=$LUKS_KEY_PRFIX$_devuuid
if _key_id=$(keyctl request logon "$_key_des" 2> /dev/null); then
mkdir "$_key_dir"
printf "%s" "$_key_des" > "$_key_dir"/description
ddebug "Succesfully get @u::%logon:$_key_des"
elif _get_luks_key_by_unlock "$_devuuid" "$_key_des"; then
_key_id=$(keyctl request logon "$_key_des")
ddebug "Succesfully get @u::%logon:$_key_des after cryptsetup"
else
derror "Failed to get logon key $_key_des. Ensure the link-volume-key option is correctly set up in /etc/crypttab (see man crypttab) and that the key is available."
derror "Failed to get logon key $_key_des. Run 'kdumpctl restart' manually to start kdump."
return 1
fi
# Let the key expire after 300 seconds
keyctl timeout "$_key_id" 300
mkdir "$_key_dir"
printf "%s" "$_key_des" > "$_key_dir"/description
done
}