mirror of
https://gitlab.alpinelinux.org/alpine/aports.git
synced 2025-04-20 03:47:16 +02:00
cryptsetup 2.7.0 contains some changes to the plain mode. Among other things, the default cipher and hashing algorithm has been changed. Additionally, since changes to the default in this regard are likely to occur in the future, cryptsetup also prints a warning now if key-size, hash, or cipher are not specified when using the plain mode. From the cryptsetup 2.7.0 release notes: > Always specify cipher, hash, and key size for plain mode […]. As we > need to upgrade algorithms from time to time because of security > reasons, cryptsetup now warns users to specify these options explicitly > in the open cryptsetup command if plain mode is used. In Alpine, we use the plain mode in the dmcrypt.initd service for swap partition encryption. The dmcrypt services does presently not specify a key size in the default options for swap encryption. This causes a warning to be emitted on boot. This commit fixes this warning by specifying a key size (256-bit, the current default). We could also consider using more sophisticated algorithms for swap partition encryption here in the future. Gentoo (where this services originated) also still uses these options. While at it, also remove the hash parameter as this is ignored in plain mode with a keyfile specified (also causes a warning).
358 lines
9.2 KiB
Bash
358 lines
9.2 KiB
Bash
#!/sbin/openrc-run
|
|
# Copyright 1999-2015 Gentoo Foundation
|
|
# Distributed under the terms of the GNU General Public License v2
|
|
|
|
depend() {
|
|
before checkfs fsck
|
|
|
|
if grep -qs ^swap= "${conf_file}" ; then
|
|
before swap
|
|
fi
|
|
}
|
|
|
|
# We support multiple dmcrypt instances based on $SVCNAME
|
|
conf_file="/etc/conf.d/${SVCNAME}"
|
|
|
|
# Get splash helpers if available.
|
|
if [ -e /sbin/splash-functions.sh ] ; then
|
|
. /sbin/splash-functions.sh
|
|
fi
|
|
|
|
# Setup mappings for an individual target/swap
|
|
# Note: This relies on variables localized in the main body below.
|
|
dm_crypt_execute() {
|
|
local dev ret mode foo
|
|
|
|
if [ -z "${target}" -a -z "${swap}" ] ; then
|
|
return
|
|
fi
|
|
|
|
# Set up default values.
|
|
: ${dmcrypt_key_timeout:=1}
|
|
: ${dmcrypt_max_timeout:=300}
|
|
: ${dmcrypt_retries:=5}
|
|
|
|
# Handle automatic look up of the source path.
|
|
if [ -z "${source}" -a -n "${loop_file}" ] ; then
|
|
source=$(losetup --show -f "${loop_file}")
|
|
fi
|
|
case ${source} in
|
|
*=*)
|
|
source="$(findfs ${source})"
|
|
;;
|
|
esac
|
|
if [ -z "${source}" ] || [ ! -e "${source}" ] ; then
|
|
ewarn "source \"${source}\" for ${target} missing, skipping..."
|
|
return
|
|
fi
|
|
|
|
if [ -n "${target}" ] ; then
|
|
# let user set options, otherwise leave empty
|
|
: ${options:=' '}
|
|
elif [ -n "${swap}" ] ; then
|
|
if cryptsetup isLuks ${source} 2>/dev/null ; then
|
|
ewarn "The swap you have defined is a LUKS partition. Aborting crypt-swap setup."
|
|
return
|
|
fi
|
|
target=${swap}
|
|
# swap contents do not need to be preserved between boots, luks not required.
|
|
# suspend2 users should have initramfs's init handling their swap partition either way.
|
|
: ${options:='-s 256 -c aes -d /dev/urandom'}
|
|
: ${pre_mount:='mkswap ${dev}'}
|
|
fi
|
|
|
|
if [ -n "${loop_file}" ] ; then
|
|
dev="/dev/mapper/${target}"
|
|
ebegin " Setting up loop device ${source}"
|
|
losetup ${source} ${loop_file}
|
|
fi
|
|
|
|
# cryptsetup:
|
|
# open <device> <name> # <device> is $source
|
|
# create <name> <device> # <name> is $target
|
|
local arg1="create" arg2="${target}" arg3="${source}"
|
|
if cryptsetup isLuks ${source} 2>/dev/null ; then
|
|
arg1="open"
|
|
arg2="${source}"
|
|
arg3="${target}"
|
|
fi
|
|
# This hack works around the lack of isLuks equivalents for alternative types
|
|
# Required feature request: https://gitlab.com/cryptsetup/cryptsetup/-/issues/824
|
|
# tcrypt can't work this way since tcryptDump requires a password
|
|
if cryptsetup bitlkDump ${source} >/dev/null 2>&1 ; then
|
|
arg1="open --type bitlk"
|
|
arg2="${source}"
|
|
arg3="${target}"
|
|
fi
|
|
if cryptsetup fvault2Dump ${source} >/dev/null 2>&1 ; then
|
|
arg1="open --type fvault2"
|
|
arg2="${source}"
|
|
arg3="${target}"
|
|
fi
|
|
|
|
# Older versions reported:
|
|
# ${target} is active:
|
|
# Newer versions report:
|
|
# ${target} is active[ and is in use.]
|
|
if cryptsetup status ${target} | grep -qE ' is active' ; then
|
|
einfo "dm-crypt mapping ${target} is already configured"
|
|
return
|
|
fi
|
|
splash svc_input_begin ${SVCNAME} >/dev/null 2>&1
|
|
|
|
# Handle keys
|
|
if [ -n "${key}" ] ; then
|
|
read_abort() {
|
|
# some colors
|
|
local ans savetty resettty
|
|
[ -z "${NORMAL}" ] && eval $(eval_ecolors)
|
|
einfon " $1? (${WARN}yes${NORMAL}/${GOOD}No${NORMAL}) "
|
|
shift
|
|
# This is ugly as s**t. But POSIX doesn't provide `read -t`, so
|
|
# we end up having to implement our own crap with stty/etc...
|
|
savetty=$(stty -g)
|
|
resettty='stty ${savetty}; trap - EXIT HUP INT TERM'
|
|
trap 'eval "${resettty}"' EXIT HUP INT TERM
|
|
stty -icanon
|
|
stty min 0 time "$(( $2 * 10 ))"
|
|
ans=$(dd count=1 bs=1 2>/dev/null) || ans=''
|
|
eval "${resettty}"
|
|
if [ -z "${ans}" ] ; then
|
|
printf '\r'
|
|
else
|
|
echo
|
|
fi
|
|
case ${ans} in
|
|
[yY]) return 0;;
|
|
*) return 1;;
|
|
esac
|
|
}
|
|
|
|
# Notes: sed not used to avoid case where /usr partition is encrypted.
|
|
mode=${key##*:} && ( [ "${mode}" = "${key}" ] || [ -z "${mode}" ] ) && mode=reg
|
|
key=${key%:*}
|
|
case "${mode}" in
|
|
gpg|reg)
|
|
# handle key on removable device
|
|
if [ -n "${remdev}" ] ; then
|
|
# temp directory to mount removable device
|
|
local mntrem="${RC_SVCDIR}/dm-crypt-remdev.$$"
|
|
if [ ! -d "${mntrem}" ] ; then
|
|
if ! mkdir -p "${mntrem}" ; then
|
|
ewarn "${source} will not be decrypted ..."
|
|
einfo "Reason: Unable to create temporary mount point '${mntrem}'"
|
|
return
|
|
fi
|
|
fi
|
|
i=0
|
|
einfo "Please insert removable device for ${target}"
|
|
while [ ${i} -lt ${dmcrypt_max_timeout} ] ; do
|
|
foo=""
|
|
if mount -n -o ro "${remdev}" "${mntrem}" 2>/dev/null >/dev/null ; then
|
|
# keyfile exists?
|
|
if [ ! -e "${mntrem}${key}" ] ; then
|
|
umount -n "${mntrem}"
|
|
rmdir "${mntrem}"
|
|
einfo "Cannot find ${key} on removable media."
|
|
read_abort "Abort" ${dmcrypt_key_timeout} && return
|
|
else
|
|
key="${mntrem}${key}"
|
|
break
|
|
fi
|
|
else
|
|
[ -e "${remdev}" ] \
|
|
&& foo="mount failed" \
|
|
|| foo="mount source not found"
|
|
fi
|
|
: $((i += 1))
|
|
read_abort "Stop waiting after $i attempts (${foo})" -t 1 && return
|
|
done
|
|
else # keyfile ! on removable device
|
|
if [ ! -e "${key}" ] ; then
|
|
ewarn "${source} will not be decrypted ..."
|
|
einfo "Reason: keyfile ${key} does not exist."
|
|
return
|
|
fi
|
|
fi
|
|
;;
|
|
*)
|
|
ewarn "${source} will not be decrypted ..."
|
|
einfo "Reason: mode ${mode} is invalid."
|
|
return
|
|
;;
|
|
esac
|
|
else
|
|
mode=none
|
|
fi
|
|
ebegin " ${target} using: ${options} ${arg1} ${arg2} ${arg3}"
|
|
if [ "${mode}" = "gpg" ] ; then
|
|
: ${gpg_options:='-q -d'}
|
|
# gpg available ?
|
|
if command -v gpg >/dev/null ; then
|
|
i=0
|
|
while [ ${i} -lt ${dmcrypt_retries} ] ; do
|
|
# paranoid, don't store key in a variable, pipe it so it stays very little in ram unprotected.
|
|
# save stdin stdout stderr "values"
|
|
timeout ${dmcrypt_max_timeout} gpg ${gpg_options} ${key} 2>/dev/null | \
|
|
cryptsetup --key-file - ${options} ${arg1} ${arg2} ${arg3}
|
|
ret=$?
|
|
# The timeout command exits 124 when it times out.
|
|
[ ${ret} -eq 0 -o ${ret} -eq 124 ] && break
|
|
: $(( i += 1 ))
|
|
done
|
|
eend ${ret} "failure running cryptsetup"
|
|
else
|
|
ewarn "${source} will not be decrypted ..."
|
|
einfo "Reason: cannot find gpg application."
|
|
einfo "You have to install gnupg first."
|
|
einfo "If you have /usr on its own partition, try copying gpg to /bin ."
|
|
fi
|
|
else
|
|
if [ "${mode}" = "reg" ] ; then
|
|
cryptsetup ${options} -d ${key} ${arg1} ${arg2} ${arg3}
|
|
ret=$?
|
|
eend ${ret} "failure running cryptsetup"
|
|
else
|
|
cryptsetup ${options} ${arg1} ${arg2} ${arg3}
|
|
ret=$?
|
|
eend ${ret} "failure running cryptsetup"
|
|
fi
|
|
fi
|
|
if [ -d "${mntrem}" ] ; then
|
|
umount -n ${mntrem} 2>/dev/null >/dev/null
|
|
rmdir ${mntrem} 2>/dev/null >/dev/null
|
|
fi
|
|
splash svc_input_end ${SVCNAME} >/dev/null 2>&1
|
|
|
|
if [ ${ret} -ne 0 ] ; then
|
|
cryptfs_status=1
|
|
else
|
|
if [ -n "${pre_mount}" ] ; then
|
|
dev="/dev/mapper/${target}"
|
|
eval ebegin \"" pre_mount: ${pre_mount}"\"
|
|
eval "${pre_mount}" > /dev/null
|
|
ewend $? || cryptfs_status=1
|
|
fi
|
|
if [ -n "${post_mount}" ] ; then
|
|
dev="/dev/mapper/${target}"
|
|
eval ebegin \"" post_mount: ${post_mount}"\"
|
|
eval "${post_mount}" > /dev/null
|
|
ewend $? || cryptfs_status=1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Lookup optional bootparams
|
|
get_bootparam_val() {
|
|
# We're given something like:
|
|
# foo=bar=cow
|
|
# Return the "bar=cow" part.
|
|
case $1 in
|
|
*=*)
|
|
echo "${1#*=}"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
start() {
|
|
local header=true cryptfs_status=0
|
|
local gpg_options key loop_file target targetline options pre_mount post_mount source swap remdev
|
|
|
|
local x
|
|
for x in $(cat /proc/cmdline) ; do
|
|
case "${x}" in
|
|
key_timeout=*)
|
|
dmcrypt_key_timeout=$(get_bootparam_val "${x}")
|
|
;;
|
|
esac
|
|
done
|
|
|
|
while read targetline <&3 ; do
|
|
case ${targetline} in
|
|
# skip comments and blank lines
|
|
""|"#"*) continue ;;
|
|
# skip service-specific openrc configs #377927
|
|
rc_*) continue ;;
|
|
esac
|
|
|
|
${header} && ebegin "Setting up dm-crypt mappings"
|
|
header=false
|
|
|
|
# check for the start of a new target/swap
|
|
case ${targetline} in
|
|
target=*|swap=*)
|
|
# If we have a target queued up, then execute it
|
|
dm_crypt_execute
|
|
|
|
# Prepare for the next target/swap by resetting variables
|
|
unset gpg_options key loop_file target options pre_mount post_mount source swap remdev
|
|
;;
|
|
|
|
gpg_options=*|remdev=*|key=*|loop_file=*|options=*|pre_mount=*|post_mount=*|source=*)
|
|
if [ -z "${target}${swap}" ] ; then
|
|
ewarn "Ignoring setting outside target/swap section: ${targetline}"
|
|
continue
|
|
fi
|
|
;;
|
|
|
|
dmcrypt_*=*)
|
|
# ignore global options
|
|
continue
|
|
;;
|
|
|
|
*)
|
|
ewarn "Skipping invalid line in ${conf_file}: ${targetline}"
|
|
;;
|
|
esac
|
|
|
|
# Queue this setting for the next call to dm_crypt_execute
|
|
eval "${targetline}"
|
|
done 3< ${conf_file}
|
|
|
|
# If we have a target queued up, then execute it
|
|
dm_crypt_execute
|
|
|
|
ewend ${cryptfs_status} "Failed to setup dm-crypt devices"
|
|
}
|
|
|
|
stop() {
|
|
local line header
|
|
|
|
# Break down all mappings
|
|
header=true
|
|
grep -E "^(target|swap)=" ${conf_file} | \
|
|
while read line ; do
|
|
${header} && einfo "Removing dm-crypt mappings"
|
|
header=false
|
|
|
|
target= swap=
|
|
eval ${line}
|
|
|
|
[ -n "${swap}" ] && target=${swap}
|
|
if [ -z "${target}" ] ; then
|
|
ewarn "invalid line in ${conf_file}: ${line}"
|
|
continue
|
|
fi
|
|
|
|
ebegin " ${target}"
|
|
cryptsetup remove ${target}
|
|
eend $?
|
|
done
|
|
|
|
# Break down loop devices
|
|
header=true
|
|
grep '^source=./dev/loop' ${conf_file} | \
|
|
while read line ; do
|
|
${header} && einfo "Detaching dm-crypt loop devices"
|
|
header=false
|
|
|
|
source=
|
|
eval ${line}
|
|
|
|
ebegin " ${source}"
|
|
losetup -d "${source}"
|
|
eend $?
|
|
done
|
|
|
|
return 0
|
|
}
|