160 lines
4.8 KiB
Bash
160 lines
4.8 KiB
Bash
#!/bin/sh
|
|
# Copyright (C) 2022 Fondries.IO
|
|
# SPDX-License-Identifier: MIT
|
|
#
|
|
# Encrypt (reencrypt) root device with LUKS2
|
|
|
|
fatal() {
|
|
echo "$1"
|
|
exit 1
|
|
}
|
|
|
|
msg() {
|
|
echo "$1"
|
|
}
|
|
|
|
cryptfs_enabled() {
|
|
return 0
|
|
}
|
|
|
|
fd_check() {
|
|
if [ ! -d "/dev/fd" ]; then
|
|
`/bin/ln -s /proc/self/fd /dev/fd`
|
|
fi
|
|
}
|
|
|
|
e2fsck_check() {
|
|
fsckret=0
|
|
if [ -n "`which e2fsck`" ]; then
|
|
fsckout=`e2fsck -p -v ${1}`
|
|
fsckret=$?
|
|
# Avoid empty newline after summary
|
|
echo "e2fsck: ${fsckout}" >/dev/kmsg
|
|
# Return code >= 4 means uncorrected / operational error
|
|
## TODO: force boot into a recovery mode or similar, as there is really not
|
|
## much we can do in case the fs is corrupted in a bad way
|
|
if [ "${fsckret}" -ge "4" ]; then
|
|
echo "e2fsck: WARNING: file system errors left uncorrected: ret ${fsckret}" >/dev/kmsg
|
|
fi
|
|
fi
|
|
return "${fsckret}"
|
|
}
|
|
|
|
cryptfs_gen_passphrase() {
|
|
# Static as at this point we just need a key for encrypting and later enrolling a new keyslot
|
|
mkdir -p /run/cryptsetup
|
|
echo -n "scle" > /run/cryptsetup/passphrase
|
|
}
|
|
|
|
cryptfs_run() {
|
|
# Similar to rootfs, we need to wait for the device to become available
|
|
C=0
|
|
delay=${bootparam_rootdelay:-1}
|
|
timeout=${bootparam_roottimeout:-5}
|
|
#while true; do
|
|
# if [ $(( $C * $delay )) -gt $timeout ]; then
|
|
# fatal "root '$bootparam_root' doesn't exist or does not contain a /dev."
|
|
# fi
|
|
|
|
# if [ -n "$bootparam_root" ]; then
|
|
# root_dev="$bootparam_root"
|
|
# if [ "`echo ${bootparam_root} | cut -c1-5`" = "UUID=" ]; then
|
|
# root_uuid=`echo $bootparam_root | cut -c6-`
|
|
# root_dev=`readlink -f /dev/disk/by-uuid/$root_uuid`
|
|
# elif [ "`echo ${bootparam_root} | cut -c1-9`" = "PARTUUID=" ]; then
|
|
# root_partuuid=`echo $bootparam_root | cut -c10-`
|
|
# root_dev=`readlink -f /dev/disk/by-partuuid/$root_partuuid`
|
|
# elif [ "`echo ${bootparam_root} | cut -c1-10`" = "PARTLABEL=" ]; then
|
|
# root_partlabel=`echo $bootparam_root | cut -c11-`
|
|
# root_dev=`readlink -f /dev/disk/by-partlabel/$root_partlabel`
|
|
# elif [ "`echo ${bootparam_root} | cut -c1-6`" = "LABEL=" ]; then
|
|
# root_label=`echo $bootparam_root | cut -c7-`
|
|
# root_dev=`readlink -f /dev/disk/by-label/$root_label`
|
|
# fi
|
|
|
|
# [ -e "$root_dev" ] && break
|
|
# fi
|
|
# debug "Sleeping for $delay second(s) to wait root to settle..."
|
|
# sleep $delay
|
|
# C=$(( $C + 1 ))
|
|
#done
|
|
|
|
flags=""
|
|
root_dev="/dev/mmcblk0p3"
|
|
mounted_dir="/data"
|
|
key_slot=8
|
|
|
|
# Identify desired token format (e.g. pkcs11, tpm2, etc) and import required functions
|
|
if [ ! -d /etc/cryptfs ]; then
|
|
fatal "No initramfs cryptfs module found"
|
|
fi
|
|
luks_token=`ls /etc/cryptfs | head -n1`
|
|
if [ -z "${luks_token}" ]; then
|
|
fatal "No valid initramfs cryptfs module found"
|
|
fi
|
|
|
|
if [ ! -d "${mounted_dir}" ]; then
|
|
/bin/mkdir -p "${mounted_dir}"
|
|
fi
|
|
|
|
fd_check
|
|
|
|
. /etc/cryptfs/${luks_token}
|
|
|
|
cryptfs_check_${luks_token}
|
|
|
|
cryptfs_gen_passphrase
|
|
|
|
if ! cryptsetup isLuks ${root_dev}; then
|
|
# Partition not yet encrypted
|
|
msg "${root_dev} not yet encrypted, encrypting with LUKS2"
|
|
e2fsck_check ${root_dev}
|
|
block_size=`dumpe2fs -h ${root_dev} 2>/dev/null | grep "^Block size" | cut -d ':' -f 2 | tr -d ' '`
|
|
block_count=`dumpe2fs -h ${root_dev} 2>/dev/null | grep "^Block count" | cut -d ':' -f 2 | tr -d ' '`
|
|
luks_size=33554432 # 32M
|
|
new_block_count=$(($block_count - $luks_size / $block_size))
|
|
resize2fs -p ${root_dev} ${new_block_count}
|
|
if [ $? -ne 0 ]; then
|
|
fatal "Failed to resize ${root_dev} to allow extra size required for luks support"
|
|
fi
|
|
|
|
cat /run/cryptsetup/passphrase | cryptsetup -v luksFormat --type luks2 --key-slot ${key_slot} --disable-locks --reduce-device-size 32m ${root_dev}
|
|
|
|
# Align label and UUID if used as boot parameter (not safe, better use the proper device path instead)
|
|
if [ -n "$root_label" ]; then
|
|
cryptsetup config --label ${root_label} ${root_dev}
|
|
fi
|
|
if [ -n "$root_uuid" ]; then
|
|
yes | cryptsetup luksUUID --uuid ${root_uuid} ${root_dev}
|
|
fi
|
|
fi
|
|
|
|
luks_name="`basename ${root_dev}`_crypt"
|
|
|
|
# Check if online encryption is still in progress
|
|
if cryptsetup luksDump ${root_dev} | grep -q "online-reencrypt"; then
|
|
# Run recovery process
|
|
cat /run/cryptsetup/passphrase | cryptsetup luksOpen ${root_dev} ${luks_name}
|
|
e2fsck_check /dev/mapper/${luks_name}
|
|
cat /run/cryptsetup/passphrase | cryptsetup -v reencrypt --resume-only ${root_dev}
|
|
cryptsetup close ${luks_name}
|
|
fi
|
|
|
|
cryptfs_pre_${luks_token}
|
|
|
|
if ! cryptsetup luksDump ${root_dev} | grep -q "clevis"; then
|
|
msg "Enrolling LUKS2 keyslot based on ${luks_token} token"
|
|
cryptfs_enroll_${luks_token} ${root_dev} ${key_slot}
|
|
fi
|
|
|
|
cryptfs_post_${luks_token} ${root_dev} ${luks_name}
|
|
|
|
e2fsck_check /dev/mapper/${luks_name}
|
|
if [ $? -gt "0" ]; then
|
|
/sbin/mkfs.ext4 -q -j /dev/mapper/${luks_name}
|
|
fi
|
|
|
|
mount ${flags} /dev/mapper/${luks_name} "$ROOTFS_DIR/data" ||
|
|
(cryptsetup luksClose ${luks_name} && fatal "Failed to mount LUKS ${luks_name}")
|
|
}
|