|
@@ -20,6 +20,21 @@
|
|
|
|
|
|
CLEVIS_UUID="cb6e8904-81ff-40da-a84a-07ab9ab5715e"
|
|
|
|
|
|
+enable_debugging() {
|
|
|
+ # Automatically enable debugging if in initramfs phase and rd.debug
|
|
|
+ if [ -e /usr/lib/dracut-lib.sh ]; then
|
|
|
+ local bashopts=$-
|
|
|
+ # Because dracut is loosely written, disable hardening options temporarily
|
|
|
+ [[ $bashopts != *u* ]] || set +u
|
|
|
+ [[ $bashopts != *e* ]] || set +e
|
|
|
+ . /usr/lib/dracut-lib.sh
|
|
|
+ [[ $bashopts != *u* ]] || set -u
|
|
|
+ [[ $bashopts != *e* ]] || set -e
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+enable_debugging
|
|
|
+
|
|
|
# valid_slot() will check whether a given slot is possibly valid, i.e., if it
|
|
|
# is a numeric value within the specified range.
|
|
|
valid_slot() {
|
|
@@ -292,9 +307,10 @@ clevis_luks_check_valid_key_or_keyfile() {
|
|
|
local KEY="${2:-}"
|
|
|
local KEYFILE="${3:-}"
|
|
|
local SLT="${4:-}"
|
|
|
+ local EXISTING_TOKEN_ID="${5:-}"
|
|
|
|
|
|
[ -z "${DEV}" ] && return 1
|
|
|
- [ -z "${KEYFILE}" ] && [ -z "${KEY}" ] && return 1
|
|
|
+ [ -z "${EXISTING_TOKEN_ID}" ] && [ -z "${KEYFILE}" ] && [ -z "${KEY}" ] && return 1
|
|
|
|
|
|
local extra_args
|
|
|
extra_args="$([ -n "${SLT}" ] && printf -- '--key-slot %s' "${SLT}")"
|
|
@@ -303,6 +319,11 @@ clevis_luks_check_valid_key_or_keyfile() {
|
|
|
${extra_args}
|
|
|
return
|
|
|
fi
|
|
|
+ if [ -n "${EXISTING_TOKEN_ID}" ]; then
|
|
|
+ cryptsetup open --test-passphrase "${DEV}" --token-id "${EXISTING_TOKEN_ID}" \
|
|
|
+ ${extra_args}
|
|
|
+ return
|
|
|
+ fi
|
|
|
|
|
|
printf '%s' "${KEY}" | cryptsetup open --test-passphrase "${DEV}" \
|
|
|
${extra_args}
|
|
@@ -313,6 +334,7 @@ clevis_luks_check_valid_key_or_keyfile() {
|
|
|
clevis_luks_unlock_device_by_slot() {
|
|
|
local DEV="${1}"
|
|
|
local SLT="${2}"
|
|
|
+ local SKIP_CHECK="${3}"
|
|
|
|
|
|
[ -z "${DEV}" ] && return 1
|
|
|
[ -z "${SLT}" ] && return 1
|
|
@@ -327,8 +349,9 @@ clevis_luks_unlock_device_by_slot() {
|
|
|
|| [ -z "${passphrase}" ]; then
|
|
|
return 1
|
|
|
fi
|
|
|
-
|
|
|
- clevis_luks_check_valid_key_or_keyfile "${DEV}" "${passphrase}" || return 1
|
|
|
+ if [ -z "${SKIP_CHECK}" ]; then
|
|
|
+ clevis_luks_check_valid_key_or_keyfile "${DEV}" "${passphrase}" || return 1
|
|
|
+ fi
|
|
|
printf '%s' "${passphrase}"
|
|
|
}
|
|
|
|
|
@@ -336,6 +359,8 @@ clevis_luks_unlock_device_by_slot() {
|
|
|
# parameter and returns the decoded passphrase.
|
|
|
clevis_luks_unlock_device() {
|
|
|
local DEV="${1}"
|
|
|
+ local SKIP_CHECK="YES"
|
|
|
+
|
|
|
[ -z "${DEV}" ] && return 1
|
|
|
|
|
|
local used_slots
|
|
@@ -346,7 +371,7 @@ clevis_luks_unlock_device() {
|
|
|
|
|
|
local slt pt
|
|
|
for slt in ${used_slots}; do
|
|
|
- if ! pt=$(clevis_luks_unlock_device_by_slot "${DEV}" "${slt}") \
|
|
|
+ if ! pt=$(clevis_luks_unlock_device_by_slot "${DEV}" "${slt}" "${SKIP_CHECK}") \
|
|
|
|| [ -z "${pt}" ]; then
|
|
|
continue
|
|
|
fi
|
|
@@ -393,13 +418,18 @@ clevis_devices_to_unlock() {
|
|
|
clevis_devices=
|
|
|
|
|
|
# Build list of devices to unlock.
|
|
|
- while read -r _ crypt_device _; do
|
|
|
+ while read -r _volname_ crypt_device _; do
|
|
|
+ # skip empty lines and lines which begin with the '#' char, per
|
|
|
+ # crypttab(5)
|
|
|
+ case $_volname_ in
|
|
|
+ ''|\#*) continue ;;
|
|
|
+ esac
|
|
|
if ! dev=$(clevis_map_device "${crypt_device}") \
|
|
|
|| [ -z "${dev}" ]; then
|
|
|
# Unable to get the device - maybe it's not available, e.g. a
|
|
|
# device on a volume group that has not been activated yet.
|
|
|
# Add it to the list anyway, since it's a pending device.
|
|
|
- clevis_devices="${clevis_devices} ${dev}"
|
|
|
+ clevis_devices="${clevis_devices} ${crypt_device}"
|
|
|
continue
|
|
|
fi
|
|
|
|
|
@@ -448,6 +478,12 @@ clevis_luks1_save_slot() {
|
|
|
echo "Error saving metadata to LUKSMeta slot ${SLOT} from ${DEV}" >&2
|
|
|
return 1
|
|
|
fi
|
|
|
+
|
|
|
+ if ! luksmeta test -d "${DEV}" 2>/dev/null >/dev/null ; then
|
|
|
+ echo "Error detected after saving metadata to LUKSMeta slot ${SLOT}, device ${DEV}" >&2
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+
|
|
|
return 0
|
|
|
}
|
|
|
|
|
@@ -734,10 +770,11 @@ clevis_luks_add_key() {
|
|
|
local NEWKEY="${3}"
|
|
|
local KEY="${4}"
|
|
|
local KEYFILE="${5:-}"
|
|
|
+ local EXISTING_TOKEN_ID="${6:-}"
|
|
|
|
|
|
[ -z "${DEV}" ] && return 1
|
|
|
[ -z "${NEWKEY}" ] && return 1
|
|
|
- [ -z "${KEY}" ] && [ -z "${KEYFILE}" ] && return 1
|
|
|
+ [ -z "${EXISTING_TOKEN_ID}" ] && [ -z "${KEY}" ] && [ -z "${KEYFILE}" ] && return 1
|
|
|
|
|
|
local extra_args='' input
|
|
|
input="$(printf '%s\n%s' "${KEY}" "${NEWKEY}")"
|
|
@@ -745,10 +782,16 @@ clevis_luks_add_key() {
|
|
|
extra_args="$(printf -- '--key-file %s' "${KEYFILE}")"
|
|
|
input="$(printf '%s' "${NEWKEY}")"
|
|
|
fi
|
|
|
+ if [ -n "${EXISTING_TOKEN_ID}" ]; then
|
|
|
+ extra_args="$(printf -- '--token-id %s' "${EXISTING_TOKEN_ID}")"
|
|
|
+ input="$(printf '%s' "${NEWKEY}")"
|
|
|
+ fi
|
|
|
+ local pbkdf_args="--pbkdf pbkdf2 --pbkdf-force-iterations 1000"
|
|
|
|
|
|
printf '%s' "${input}" | cryptsetup luksAddKey --batch-mode \
|
|
|
--key-slot "${SLT}" \
|
|
|
"${DEV}" \
|
|
|
+ ${pbkdf_args} \
|
|
|
${extra_args}
|
|
|
}
|
|
|
|
|
@@ -759,6 +802,7 @@ clevis_luks_update_key() {
|
|
|
local NEWKEY="${3}"
|
|
|
local KEY="${4}"
|
|
|
local KEYFILE="${5:-}"
|
|
|
+ local EXISTING_TOKEN_ID="${6:-}"
|
|
|
|
|
|
[ -z "${DEV}" ] && return 1
|
|
|
[ -z "${NEWKEY}" ] && return 1
|
|
@@ -768,7 +812,7 @@ clevis_luks_update_key() {
|
|
|
local in_place
|
|
|
clevis_luks_check_valid_key_or_keyfile "${DEV}" \
|
|
|
"${KEY}" "${KEYFILE}" \
|
|
|
- "${SLT}" 2>/dev/null \
|
|
|
+ "${SLT}" "${EXISTING_TOKEN_ID}" 2>/dev/null \
|
|
|
&& in_place=true
|
|
|
|
|
|
local input extra_args=
|
|
@@ -777,11 +821,19 @@ clevis_luks_update_key() {
|
|
|
extra_args="$(printf -- '--key-file %s' "${KEYFILE}")"
|
|
|
input="$(printf '%s' "${NEWKEY}")"
|
|
|
fi
|
|
|
+ if [ -n "${EXISTING_TOKEN_ID}" ]; then
|
|
|
+ extra_args="$(printf -- '--token-id %s' "${EXISTING_TOKEN_ID}")"
|
|
|
+ input="$(printf '%s' "${NEWKEY}")"
|
|
|
+ fi
|
|
|
+
|
|
|
+ local pbkdf_args="--pbkdf pbkdf2 --pbkdf-force-iterations 1000"
|
|
|
|
|
|
if [ -n "${in_place}" ]; then
|
|
|
printf '%s' "${input}" | cryptsetup luksChangeKey "${DEV}" \
|
|
|
--key-slot "${SLT}" \
|
|
|
- --batch-mode ${extra_args}
|
|
|
+ --batch-mode \
|
|
|
+ ${pbkdf_args} \
|
|
|
+ ${extra_args}
|
|
|
return
|
|
|
fi
|
|
|
|
|
@@ -803,6 +855,7 @@ clevis_luks_save_key_to_slot() {
|
|
|
local KEY="${4}"
|
|
|
local KEYFILE="${5:-}"
|
|
|
local OVERWRITE="${6:-}"
|
|
|
+ local EXISTING_TOKEN_ID="${7:-}"
|
|
|
|
|
|
[ -z "${DEV}" ] && return 1
|
|
|
[ -z "${SLT}" ] && return 1
|
|
@@ -820,13 +873,13 @@ clevis_luks_save_key_to_slot() {
|
|
|
[ -n "${OVERWRITE}" ] || return 1
|
|
|
|
|
|
clevis_luks_update_key "${DEV}" "${SLT}" \
|
|
|
- "${NEWKEY}" "${KEY}" "${KEYFILE}"
|
|
|
+ "${NEWKEY}" "${KEY}" "${KEYFILE}" "${EXISTING_TOKEN_ID}"
|
|
|
return
|
|
|
fi
|
|
|
|
|
|
# Add a new key.
|
|
|
clevis_luks_add_key "${DEV}" "${SLT}" \
|
|
|
- "${NEWKEY}" "${KEY}" "${KEYFILE}"
|
|
|
+ "${NEWKEY}" "${KEY}" "${KEYFILE}" "${EXISTING_TOKEN_ID}"
|
|
|
}
|
|
|
|
|
|
# clevis_luks_generate_key() generates a new key for use with clevis.
|
|
@@ -835,6 +888,7 @@ clevis_luks_generate_key() {
|
|
|
[ -z "${DEV}" ] && return 1
|
|
|
|
|
|
local dump filter bits
|
|
|
+ local MAX_ENTROPY_BITS=256 # Maximum allowed by pwmake.
|
|
|
dump=$(cryptsetup luksDump "${DEV}")
|
|
|
if cryptsetup isLuks --type luks1 "${DEV}"; then
|
|
|
filter="$(echo "${dump}" | sed -rn 's|MK bits:[ \t]*([0-9]+)|\1|p')"
|
|
@@ -846,6 +900,9 @@ clevis_luks_generate_key() {
|
|
|
fi
|
|
|
|
|
|
bits="$(echo -n "${filter}" | sort -n | tail -n 1)"
|
|
|
+ if [ "${bits}" -gt "${MAX_ENTROPY_BITS}" ]; then
|
|
|
+ bits="${MAX_ENTROPY_BITS}"
|
|
|
+ fi
|
|
|
pwmake "${bits}"
|
|
|
}
|
|
|
|
|
@@ -918,15 +975,17 @@ clevis_luks_do_bind() {
|
|
|
local OVERWRITE="${7:-}"
|
|
|
local KEY="${8:-}"
|
|
|
local KEYFILE="${9:-}"
|
|
|
+ local EXISTING_TOKEN_ID="${10:-}"
|
|
|
|
|
|
[ -z "${DEV}" ] && return 1
|
|
|
[ -z "${PIN}" ] && return 1
|
|
|
[ -z "${CFG}" ] && return 1
|
|
|
|
|
|
-
|
|
|
if ! clevis_luks_check_valid_key_or_keyfile "${DEV}" \
|
|
|
"${KEY}" \
|
|
|
"${KEYFILE}" \
|
|
|
+ "" \
|
|
|
+ "${EXISTING_TOKEN_ID}" \
|
|
|
&& ! KEY="$(clevis_luks_get_existing_key "${DEV}" \
|
|
|
"Enter existing LUKS password: " \
|
|
|
"recover")"; then
|
|
@@ -941,12 +1000,16 @@ clevis_luks_do_bind() {
|
|
|
fi
|
|
|
|
|
|
# Encrypt the new key.
|
|
|
- jwe="$(printf '%s' "${newkey}" | clevis encrypt "${PIN}" "${CFG}" ${YES})"
|
|
|
+ if ! jwe="$(printf '%s' "${newkey}" | clevis encrypt "${PIN}" "${CFG}" \
|
|
|
+ ${YES})" || [ -z "${jwe}" ]; then
|
|
|
+ echo "Unable to perform encryption with PIN '${PIN}' and config '${CFG}'" >&2
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
|
|
|
# We can proceed to binding, after backing up the LUKS header and
|
|
|
# metadata.
|
|
|
local CLEVIS_TMP_DIR
|
|
|
-
|
|
|
+ mkdir -p "${TMPDIR:-/tmp}"
|
|
|
if ! CLEVIS_TMP_DIR="$(mktemp -d)" || [ -z "${CLEVIS_TMP_DIR}" ]; then
|
|
|
echo "Unable to create a a temporary dir for device backup/restore" >&2
|
|
|
return 1
|
|
@@ -971,7 +1034,7 @@ clevis_luks_do_bind() {
|
|
|
|
|
|
if ! clevis_luks_save_key_to_slot "${DEV}" "${SLT}" \
|
|
|
"${newkey}" "${KEY}" "${KEYFILE}" \
|
|
|
- "${OVERWRITE}"; then
|
|
|
+ "${OVERWRITE}" "${EXISTING_TOKEN_ID}"; then
|
|
|
echo "Unable to save/update key slot; operation cancelled" >&2
|
|
|
clevis_luks_restore_dev "${CLEVIS_TMP_DIR}" || :
|
|
|
rm -rf "${CLEVIS_TMP_DIR}"
|
|
@@ -992,12 +1055,19 @@ clevis_luks_do_bind() {
|
|
|
}
|
|
|
|
|
|
# clevis_luks_luks2_supported() indicates whether we support LUKS2 devices.
|
|
|
-# Suppor is determined at build time.
|
|
|
+# Support is determined at build time.
|
|
|
function clevis_luks_luks2_supported() {
|
|
|
# We require cryptsetup >= 2.0.4 to fully support LUKSv2.
|
|
|
return @OLD_CRYPTSETUP@
|
|
|
}
|
|
|
|
|
|
+# clevis_luks_luks2_existing_token_id_supported() indicates whether
|
|
|
+# cryptsetup allows token id for passphrase providing
|
|
|
+function clevis_luks_luks2_existing_token_id_supported() {
|
|
|
+ # We require cryptsetup >= 2.6.0 to fully support LUKSv2 addkey/open by token ID
|
|
|
+ return @OLD_CRYPTSETUP_EXISTING_TOKEN_ID@
|
|
|
+}
|
|
|
+
|
|
|
# clevis_luks_type() returns the LUKS type of a device, e.g. "luks1".
|
|
|
clevis_luks_type() {
|
|
|
local DEV="${1}"
|