This repository has been archived on 2024-09-01. You can view files and clone it, but cannot push or open issues or pull requests.
al-installer/src/lib/luks.sh

209 lines
6.4 KiB
Bash

#!/usr/bin/bash
# vim:ft=sh:fdm=marker:fmr={,}
# archlabs installer library script file
# this file is not meant to be run directly
# sourcing this file in a non bash shell is not advised
# shellcheck disable=2154,2034
declare -g LUKS=""
declare -g LUKS_DEV=""
declare -g LUKS_PART=""
declare -g LUKS_PASS=""
declare -g LUKS_UUID=""
declare -g LUKS_NAME="cryptroot"
luks_open()
{
LUKS_PART=""
modprobe -a dm-mod dm_crypt
umount_dir $MNT
find_partitions 'part|crypt|lvm' || return 1
tput civis
if (( COUNT == 1 )); then
LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
infobox "$_LuksOpen" "${_OnlyOne}: $LUKS_PART\n" 1
else
tput civis
if ! LUKS_PART="$(menubox "$_LuksOpen" "$_LuksMenuBody" 0 0 0 $PARTS)"; then
return 1
fi
fi
# get password and name for encryption
luks_pass "$_LuksOpen" "$LUKS_NAME" || return 1
infobox "$_LuksOpen" "$_LuksWaitBody $LUKS_NAME $_LuksWaitBody2 $LUKS_PART\n" 0
cryptsetup open --type luks $LUKS_PART "$LUKS_NAME" <<< "$(openssl enc -pbkdf2 -a -d -salt -pass pass:$SALT <<< "$LUKS_PASS")" 2>$ERR
echeck "cryptsetup open --type luks $LUKS_PART $LUKS_NAME"
LUKS=' encrypted'
luks_show
return 0
}
luks_pass()
{
local title="$1"
local name="$2"
LUKS_PASS=""
LUKS_NAME=""
tput cnorm
local values
if ! values="$(dialog --stdout --separator '~' --ok-label "Submit" --backtitle "$BT" \
--title " $title " --insecure --mixedform "$_LuksOpenBody" 16 75 4 \
"$_Name" 1 1 "$name" 1 $((${#_Name} + 2)) 71 0 0 \
"$_Password" 2 1 "" 2 $((${#_Password} + 2)) 71 0 1 \
"$_Password2" 3 1 "" 3 $((${#_Password2} + 2)) 71 0 1 |
openssl enc -pbkdf2 -a -salt -pass pass:$SALT)"; then
return 1
fi
name="$(openssl enc -pbkdf2 -a -d -salt -pass pass:$SALT <<< "$values" |
awk -F'~' '{print $1}')"
# all of this is a bit hacky, but we don't ever want the passwords to be stored in plain text
# so it decrypts the string '$values', gets the field we want, and re-encrypts it
local pass pass2
pass="$(openssl enc -pbkdf2 -a -d -salt -pass pass:$SALT <<< "$values" |
awk -F'~' '{print $2}' | openssl enc -pbkdf2 -a -salt -pass pass:$SALT)"
pass2="$(openssl enc -pbkdf2 -a -d -salt -pass pass:$SALT <<< "$values" |
awk -F'~' '{print $3}' | openssl enc -pbkdf2 -a -salt -pass pass:$SALT)"
# due to the encryption the string while encrypted will not be empty
local empty
empty="$(openssl enc -pbkdf2 -a -salt -pass pass:$SALT <<< "")"
if [[ $pass == "$empty" || "$pass" != "$pass2" ]]; then
msgbox "$_ErrTitle" "$_PassErr\n$_TryAgain"
luks_pass "$title" "$name" || return 1
fi
LUKS_PASS="$pass"
LUKS_NAME="$name"
return 0
}
luks_setup()
{
LUKS_PART=""
modprobe -a dm-mod dm_crypt
umount_dir $MNT
if [[ ! $ROOT_PART || $LVM ]]; then
find_partitions 'part|lvm' || return 1
[[ $BOOT_PART != "" ]] && decr_count "$BOOT_PART"
if (( COUNT == 1 )); then
LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
infobox "$_LuksEncrypt" "${_OnlyOne}: $LUKS_PART\n" 1
else
tput civis
if ! LUKS_PART="$(menubox "$_LuksEncrypt" "$_LuksEncryptBody" 0 0 0 $PARTS)"; then
return 1
fi
fi
else
infobox "$_PrepMount" "\nUsing root partition created earlier: $ROOT_PART\n" 1
LUKS_PART="$ROOT_PART"
fi
# get password and name for encrypted device
luks_pass "$_LuksEncrypt" "$LUKS_NAME" || return 1
return 0
}
luks_default()
{
luks_setup || return 1
infobox "$_LuksEncrypt" "$_LuksWaitBody $LUKS_NAME $_LuksWaitBody2 $LUKS_PART\n" 0
cryptsetup -q luksFormat $LUKS_PART <<< "$(openssl enc -pbkdf2 -a -d -salt -pass pass:$SALT <<< "$LUKS_PASS")" 2>$ERR
echeck "cryptsetup -q luksFormat $LUKS_PART"
cryptsetup open $LUKS_PART "$LUKS_NAME" <<< "$(openssl enc -pbkdf2 -a -d -salt -pass pass:$SALT <<< "$LUKS_PASS")" 2>$ERR
echeck "cryptsetup open $LUKS_PART $LUKS_NAME"
export LUKS=' encrypted'
luks_show
return 0
}
luks_keycmd()
{
if luks_setup; then
tput cnorm
local cipher
if ! cipher="$(getinput "$_PrepLUKS" "$_LuksCipherKey" "-s 512 -c aes-xts-plain64")"; then
return 1
fi
infobox "$_LuksEncryptAdv" "$_LuksWaitBody $LUKS_NAME $_LuksWaitBody2 $LUKS_PART\n" 0
cryptsetup -q $cipher luksFormat $LUKS_PART <<< "$(openssl enc -pbkdf2 -a -d -salt -pass pass:$SALT <<< "$LUKS_PASS")" 2>$ERR
echeck "cryptsetup -q $cipher luksFormat $LUKS_PART"
cryptsetup open $LUKS_PART "$LUKS_NAME" <<< "$(openssl enc -pbkdf2 -a -d -salt -pass pass:$SALT <<< "$LUKS_PASS")" 2>$ERR
echeck "cryptsetup open $LUKS_PART $LUKS_NAME"
luks_show
return 0
fi
return 1
}
luks_show()
{
tput civis
sleep 0.5
msgbox "$_LuksEncrypt" "${_LuksEncryptSucc}\n$(lsblk $LUKS_PART -o NAME,MODEL,TYPE,FSTYPE,SIZE)"
}
luks_menu()
{
tput civis
local choice
choice="$(menubox "$_PrepLUKS" "${_LuksMenuBody}${_LuksMenuBody2}${_LuksMenuBody3}" 0 0 0 \
"$_LuksEncrypt" "cryptsetup -q luksFormat" \
"$_LuksOpen" "cryptsetup open --type luks" \
"$_LuksEncryptAdv" "cryptsetup -q -s -c luksFormat" \
"$_Back" "-")"
case $choice in
"$_LuksEncrypt") luks_default && return 0 ;;
"$_LuksOpen") luks_open && return 0 ;;
"$_LuksEncryptAdv") luks_keycmd && return 0 ;;
*) return 0
esac
luks_menu
}
luks_keyfile()
{
# Only used when choosing grub as bootloader.
# Without a keyfile, during boot the user will be asked
# to enter password for decryption twice, this is annoying
if [[ ! -e $MNT/crypto_keyfile.bin ]]; then
infobox "$_LuksKeyFileTitle" "$_LuksKeyFileCreate" 0
printf "$_LuksKeyFileCreate"
local n
n="$(lsblk -lno NAME,UUID,TYPE | awk "/$LUKS_UUID/"' && /part|crypt|lvm/ {print $1}')"
local mkkey="dd bs=512 count=8 if=/dev/urandom of=/crypto_keyfile.bin"
mkkey="$mkkey && chmod 000 /crypto_keyfile.bin"
mkkey="$mkkey && cryptsetup luksAddKey /dev/$n /crypto_keyfile.bin <<< '$(openssl enc -pbkdf2 -a -d -salt -pass pass:$SALT <<< "$LUKS_PASS")'"
chrun "$mkkey"
sed -i 's/FILES=()/FILES=(\/crypto_keyfile.bin)/g' $MNT/etc/mkinitcpio.conf 2>$ERR
fi
return 0
}