#!/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_datadelay:-1} timeout=${bootparam_datatimeout:-5} while true; do if [ $(( $C * $delay )) -gt $timeout ]; then fatal "root '$bootparam_data' doesn't exist or does not contain a /dev." fi if [ -n "$bootparam_data" ]; then root_dev="$bootparam_data" if [ "`echo ${bootparam_data} | cut -c1-5`" = "UUID=" ]; then root_uuid=`echo $bootparam_data | cut -c6-` root_dev=`readlink -f /dev/disk/by-uuid/$root_uuid` elif [ "`echo ${bootparam_data} | cut -c1-9`" = "PARTUUID=" ]; then root_partuuid=`echo $bootparam_data | cut -c10-` root_dev=`readlink -f /dev/disk/by-partuuid/$root_partuuid` elif [ "`echo ${bootparam_data} | cut -c1-10`" = "PARTLABEL=" ]; then root_partlabel=`echo $bootparam_data | cut -c11-` root_dev=`readlink -f /dev/disk/by-partlabel/$root_partlabel` elif [ "`echo ${bootparam_data} | cut -c1-6`" = "LABEL=" ]; then root_label=`echo $bootparam_data | 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}") }