The default keyscript for using a smartcard forces the use of the smartcard. If the card is not found the system fails to boot.
I want the script to allow recovery in case I forget to put the card in before boot but I also want the option to type a passphrase in case I don't have the smartcard. To do this I created a new version of the keyscript. Getting the system to use it is a challenge.
First I create /usr/lib/cryptsetup/scripts/decrypt_gnupg-sc-fallback using the following code. It is based on the current script /usr/lib/cryptsetup/scripts/decrypt_gnupg-sc.
#!/bin/sh
if [ -d "/cryptroot/gnupghome" ]; then
export GNUPGHOME="/cryptroot/gnupghome"
fi
run_gpg() {
gpg --no-options --trust-model=always "$@"
}
decrypt_gpg () {
local console _
if ! GPG_TTY="$(tty)"; then
read console _ </proc/consoles
GPG_TTY="/dev/$console"
fi
export GPG_TTY
if ! run_gpg --decrypt -- "$1"; then
return 1
fi
return 0
}
if [ ! -x /usr/bin/gpg ]; then
echo "$0: /usr/bin/gpg is not available" >&2
exit 1
fi
if [ -z "$1" ] || [ ! -f "$1" ]; then
echo "$0: missing key as argument" >&2
exit 1
fi
# `gpg-connect-agent LEARN /bye` is another (lighter) way, but it's
# harder to retrieve the return code
# get the return status from this command
if ! run_gpg --batch --quiet --no-tty --card-status >/dev/null; then
echo "No OpenPGP SmartCard detected. Do you want to bypass? [Y/n]" >&2
read ANSWER
if [ "$ANSWER" = "" ] || [ "$ANSWER" = "y" ] || [ "$ANSWER" = "Y" ] ; then
/lib/cryptsetup/askpass "Enter LUKS passphrase:"
else
echo "Please insert OpenPGP SmartCard..." >&2
until run_gpg --batch --quiet --no-tty --card-status; do
sleep 1
done >/dev/null 2>&1
decrypt_gpg "$1"
fi
else
decrypt_gpg "$1"
fi
exit $?
[edit. THIS DOES NOT WORK???]
crypttab must be modified to use the new keyscript. This is the standard process for encrypted LUKS root.
sdaX_crypt UUID=xyz... /etc/cryptsetup-initramfs/cryptkey.gpg luks,keyscript=decrypt_gnupg-sc-fallback
For some unknown reason when I try to use a custom keyscript file name the system fails to boot properly. If I copy the same code into an existing script it works. THIS IS REALLY ANNOYING. To work around this I rename the original script and replace it with my own. This only works until the package updates the file and then I have to set it up again.
mv /lib/cryptsetup/scripts/decrypt_gnupg-sc /lib/cryptsetup/scripts/decrypt_gnupg-sc.orig
cp /lib/cryptsetup/scripts/decrypt_gnupg-sc-fallback /lib/cryptsetup/scripts/decrypt_gnupg-sc
Of course I have to change crypttab to reflect this new reality
sdaX_crypt UUID=xyz... /etc/cryptsetup-initramfs/cryptkey.gpg luks,keyscript=decrypt_gnupg-sc
Lastly, the initramfs has to be updated to include the new code and settings
update-initramfs -u -k all
After a restart the boot process will check for the smartcard before taking the next action.
If the card is found it will be used to decrypt the root partition. The system will prompt for the PIN. If the user does not want it to be used the card can be unplugged before boot.
If the card is not found the system will present the option to bypass the smartcard. If the user chooses yes it will ask for a passphrase to decrypt /root.
If the user chooses no she is instructed to plug in the smartcard. The system watches for the card insert and then asks for the PIN. Once the PIN is entered the smartcard is used to decrypt /root.
Technically 'use the smartcard to decrypt root' means 'use the smartcard to decrypt a binary keyfile that is used to decrypt the LUKS partition that is /root'.
package updates overwrite keyscripts
Since updates may overwrite our custom fallback code we set the system to always reset the file to what we want on each shutdown. In theory, reverted code will replaced on shutdown. This does make the shutdown take longer. The script only runs the update when the script file has been reverted.
First put the following text into a new file named /etc/init.d/decrypt_gnupg-sc-fallback
file1=/usr/lib/cryptsetup/scripts/decrypt_gnupg-sc
file2=/usr/lib/cryptsetup/scripts/decrypt_gnupg-sc-fallback
diff $file1 $file2 > /dev/null
if [ $? -eq 1 ] ; then
echo "fixing '$file1'"
cp $file2 $file1
update-initramfs -u
fi
Now set up the shutdown process
chmod a+x /etc/init.d/decrypt_gnupg-sc-fallback
ln -s /etc/init.d/decrypt_gnupg-sc-fallback /etc/rc6.d/K99decrypt_gnupg-sc-fallback