heads/initrd/init
Kyle Rankin d937426306
Use the Librem Key as a TPM work-alike in the absence of a TPM
On machines without a TPM, we'd still like some way for the BIOS to
attest that it has not been modified. With a Librem Key, we can have the
BIOS use its own ROM measurement converted to a SHA256sum and truncated
so it fits within an HOTP secret. Like with a TPM, a malicious BIOS with
access to the correct measurements can send pre-known good measurements
to the Librem Key.

This approach provides one big drawback in that we have to truncate the
SHA256sum to 20 characters so that it fits within the limitations of
HOTP secrets. This means the possibility of collisions is much higher
but again, an attacker could also capture and spoof an existing ROM's
measurements if they have prior access to it, either with this approach
or with a TPM.

Signed-off-by: Kyle Rankin <kyle.rankin@puri.sm>
2023-06-14 09:58:34 -04:00

179 lines
5.0 KiB
Bash
Executable File

#! /bin/ash
# Note this is used on legacy-flash boards that lack bash, it runs with busybox
# ash. Calls to bash scripts must be guarded by checking config.
mknod /dev/ttyprintk c 5 3
echo "hello world" > /dev/ttyprintk
# Setup our path
export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
# This is the very first script invoked by the Linux kernel and is
# running out of the ram disk. There are no fileysstems mounted.
# It is important to have a way to invoke a recovery shell in case
# the boot scripts are messed up, but also important to modify the
# PCRs if this happens to prevent the TPM disk keys from being revealed.
# First thing it is vital to mount the /dev and other system directories
mkdir /proc /sys /dev /tmp /boot /media 2>&- 1>&-
mount /dev 2>/dev/ttyprintk
mount /proc 2>/dev/ttyprintk
mount /sys 2>/dev/ttyprintk
if [ "$CONFIG_LINUXBOOT" = "y" ]; then
mount /sys/firmware/efi/efivars
fi
# Setup the pty psudeo filesystem
mkdir /dev/pts
mount /dev/pts 2>/dev/ttyprintk
if [ ! -r /dev/ptmx ]; then
ln -s /dev/pts/ptmx /dev/ptmx
fi
# Needed by bash
[ -e /dev/stdin ] || ln -s /proc/self/fd/0 /dev/stdin
[ -e /dev/stdout ] || ln -s /proc/self/fd/1 /dev/stdout
[ -e /dev/stderr ] || ln -s /proc/self/fd/2 /dev/stderr
[ -e /dev/fd ] || ln -s /proc/self/fd /dev/fd
# Recovery shells will erase anything from here
mkdir -p /tmp/secret
# Now it is safe to print a banner
if [ -r /etc/motd ]; then
cat /etc/motd > /dev/tty0
fi
# Load the date from the hardware clock, setting it in local time
hwclock -l -s
# Read the system configuration parameters
. /etc/ash_functions
. /etc/config
TRACE "Under init"
# set CONFIG_TPM dynamically before init
if [ ! -e /dev/tpm0 ]; then
CONFIG_TPM='n'
CONFIG_TPM2_TOOLS='n'
fi
#Specify whiptail background colors cues under FBWhiptail only
if [ -x /bin/fbwhiptail ]; then
export BG_COLOR_WARNING="${CONFIG_WARNING_BG_COLOR:-"--background-gradient 0 0 0 150 125 0"}"
export BG_COLOR_ERROR="${CONFIG_ERROR_BG_COLOR:-"--background-gradient 0 0 0 150 0 0"}"
else
export BG_COLOR_WARNING="${CONFIG_WARNING_BG_COLOR:-""}"
export BG_COLOR_ERROR="${CONFIG_ERROR_BG_COLOR:-""}"
fi
if [ "$CONFIG_TPM" = "y" ]; then
# Initialize tpm2 encrypted sessions here
tpmr startsession
fi
if [ "$CONFIG_COREBOOT" = "y" ]; then
[ -x /bin/bash ] && /bin/cbfs-init
fi
if [ "$CONFIG_LINUXBOOT" = "y" ]; then
/bin/uefi-init
fi
# Set GPG_TTY before calling gpg in key-init
export GPG_TTY=/dev/console
[ -x /bin/bash ] && /bin/key-init
# Setup recovery serial shell
if [ ! -z "$CONFIG_BOOT_RECOVERY_SERIAL" ]; then
stty -F "$CONFIG_BOOT_RECOVERY_SERIAL" 115200
pause_recovery 'Console recovery shell' \
< "$CONFIG_BOOT_RECOVERY_SERIAL" \
> "$CONFIG_BOOT_RECOVERY_SERIAL" 2>&1 &
fi
# load USB modules for boards using a USB keyboard
if [ "$CONFIG_USB_KEYBOARD" = "y" ]; then
enable_usb
fi
# If the user has been holding down r, enter a recovery shell
# otherwise immediately start the configured boot script.
# We don't print a prompt, since this is a near instant timeout.
read \
-t 0.1 \
-n 1 \
boot_option
echo
if [ "$boot_option" = "r" ]; then
# Start an interactive shell
recovery 'User requested recovery shell'
# just in case...
if [ "$CONFIG_TPM" = "y" ]; then
tpmr extend -ix 4 -ic recovery
fi
exec /bin/sh
exit
fi
# Override CONFIG_TPM and CONFIG_TPM2_TOOLS from /etc/config with runtime value
# determined above.
#
# Values in user config have higher priority during combining thus effectively
# changing the value for the rest of the scripts which source /tmp/config.
echo "export CONFIG_TPM=\"$CONFIG_TPM\"" >> /etc/config.user
echo "export CONFIG_TPM2_TOOLS=\"$CONFIG_TPM2_TOOLS\"" >> /etc/config.user
combine_configs
. /tmp/config
# export firmware version
export FW_VER=$(dmesg | grep 'DMI' | grep -o 'BIOS.*' | cut -f2- -d ' ')
# chop off date, since will always be epoch w/timeless builds
FW_VER=${FW_VER::-10}
# Add our boot devices into the /etc/fstab, if they are defined
# in the configuration file.
if [ ! -z "$CONFIG_BOOT_DEV" ]; then
echo >> /etc/fstab "$CONFIG_BOOT_DEV /boot auto defaults,ro 0 0"
fi
if [ ! -x "$CONFIG_BOOTSCRIPT" -a ! -x "$CONFIG_BOOTSCRIPT_NETWORK" ]; then
recovery 'Boot script missing? Entering recovery shell'
else
if [ -x "$CONFIG_BOOTSCRIPT_NETWORK" ]; then
echo '***** Network Boot:' $CONFIG_BOOTSCRIPT_NETWORK
$CONFIG_BOOTSCRIPT_NETWORK
echo '***** Network Boot Completed:' $CONFIG_BOOTSCRIPT_NETWORK
# not blocking
fi
if [ -x "$CONFIG_BOOTSCRIPT" ]; then
echo '***** Normal boot:' $CONFIG_BOOTSCRIPT
if [ -x /bin/setsid ] && [ -x /bin/agetty ]; then
for console in $CONFIG_BOOT_EXTRA_TTYS; do
setsid agetty -aroot -l"$CONFIG_BOOTSCRIPT" "$console" linux &
done
fi
exec "$CONFIG_BOOTSCRIPT"
# We should never reach here, but just in case...
recovery 'Boot script failure? Entering recovery shell'
else
# wait for boot via network to occur
pause_recovery 'Override network boot. Entering recovery shell'
fi
fi
# belts and suspenders, just in case...
if [ "$CONFIG_TPM" = "y" ]; then
tpmr extend -ix 4 -ic recovery
fi
exec /bin/sh