mirror of
https://github.com/linuxboot/heads.git
synced 2024-12-18 20:47:55 +00:00
Implement Restricted Boot Mode
Restricted Boot mode only allows booting from signed files, whether that is signed kernels in /boot or signed ISOs on mounted USB disks. This disables booting from abitrary USB disks as well as the forced "unsafe" boot mode. This also disables the recovery console so you can't bypass this mode simply by running kexec manually. Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
This commit is contained in:
parent
4bc6159ab6
commit
79da79a5e4
@ -29,6 +29,8 @@ while true; do
|
||||
else
|
||||
# check current PureBoot Mode
|
||||
BASIC_MODE="$(load_config_value CONFIG_PUREBOOT_BASIC)"
|
||||
# check current Restricted Boot Mode
|
||||
RESTRICTED_BOOT="$(load_config_value CONFIG_RESTRICTED_BOOT)"
|
||||
BASIC_NO_AUTOMATIC_DEFAULT="$(load_config_value CONFIG_BASIC_NO_AUTOMATIC_DEFAULT)"
|
||||
|
||||
dynamic_config_options=()
|
||||
@ -45,6 +47,7 @@ while true; do
|
||||
'D' ' Change the root directories to hash' \
|
||||
'B' ' Check root hashes at boot' \
|
||||
'P' " $(get_config_display_action "$BASIC_MODE") PureBoot Basic Mode" \
|
||||
'L' " $(get_config_display_action "$RESTRICTED_BOOT") Restricted Boot" \
|
||||
)
|
||||
fi
|
||||
|
||||
@ -247,7 +250,10 @@ while true; do
|
||||
fi
|
||||
;;
|
||||
"P" )
|
||||
if [ "$BASIC_MODE" = "n" ]; then
|
||||
if ! [ "$RESTRICTED_BOOT" = n ]; then
|
||||
whiptail $BG_COLOR_ERROR --title 'Restricted Boot Active' \
|
||||
--msgbox "Disable Restricted Boot to enable Basic Mode." 0 80
|
||||
elif [ "$BASIC_MODE" = "n" ]; then
|
||||
if (whiptail --title 'Enable PureBoot Basic Mode?' \
|
||||
--yesno "This will remove all signature checking on the firmware
|
||||
\nand boot files, and disable use of the Librem Key.
|
||||
@ -274,6 +280,61 @@ while true; do
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
"L" )
|
||||
if [ "$RESTRICTED_BOOT" = "n" ]; then
|
||||
if (whiptail --title 'Enable Restricted Boot Mode?' \
|
||||
--yesno "This will disable booting from any unsigned files,
|
||||
\nincluding kernels that have not yet been signed,
|
||||
\n.isos without signatures, raw USB disks,
|
||||
\nand will disable failsafe boot mode.
|
||||
\n\nThis will also disable the recovery console.
|
||||
\n\nDo you want to proceed?" 0 80) then
|
||||
|
||||
set_config /etc/config.user "CONFIG_RESTRICTED_BOOT" "y"
|
||||
combine_configs
|
||||
|
||||
whiptail --title 'Config change successful' \
|
||||
--msgbox "Restricted Boot mode enabled;\nsave the config change and reboot for it to go into effect." 0 80
|
||||
|
||||
fi
|
||||
else
|
||||
if (whiptail --title 'Disable Restricted Boot Mode?' \
|
||||
--yesno "This will allow booting from unsigned devices,
|
||||
\nand will re-enable failsafe boot mode.
|
||||
\n\nThis will also RESET the TPM and re-enable the recovery console.
|
||||
\n\nProceeding will automatically update the boot firmware, reset TPM and reboot!
|
||||
\n\nDo you want to proceed?" 0 80) then
|
||||
|
||||
# Wipe the TPM TOTP/HOTP secret before flashing. Otherwise, enabling
|
||||
# Restricted Boot again might restore the firmware to an identical
|
||||
# state, and there would be no evidence that it had been temporarily
|
||||
# disabled.
|
||||
if ! wipe-totp >/dev/null 2>/tmp/error; then
|
||||
ERROR=$(tail -n 1 /tmp/error | fold -s)
|
||||
whiptail $BG_COLOR_ERROR --title 'ERROR: erasing TOTP secret' \
|
||||
--msgbox "Erasing TOTP Secret Failed\n\n${ERROR}" 0 80
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# We can't allow Restricted Boot to be disabled without flashing the
|
||||
# firmware - this would allow the use of unrestricted mode without
|
||||
# leaving evidence in the firmware. Disable it by flashing the new
|
||||
# config directly.
|
||||
FLASH_USER_CONFIG=/tmp/config-gui-config-user
|
||||
cp /etc/config.user "$FLASH_USER_CONFIG"
|
||||
set_config "$FLASH_USER_CONFIG" "CONFIG_RESTRICTED_BOOT" "n"
|
||||
|
||||
read_rom /tmp/config-gui.rom
|
||||
|
||||
replace_rom_file /tmp/config-gui.rom "heads/initrd/etc/config.user" "$FLASH_USER_CONFIG"
|
||||
|
||||
/bin/flash.sh /tmp/config-gui.rom
|
||||
whiptail --title 'BIOS Updated Successfully' \
|
||||
--msgbox "BIOS updated successfully.\n\nIf your keys have changed, be sure to re-sign all files in /boot\nafter you reboot.\n\nPress Enter to reboot" 0 80
|
||||
/bin/reboot
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
"A" )
|
||||
if [ "$BASIC_NO_AUTOMATIC_DEFAULT" = "n" ]; then
|
||||
if (whiptail --title 'Disable automatic default boot?' \
|
||||
|
@ -7,6 +7,12 @@ set -e -o pipefail
|
||||
|
||||
TRACE "Under /bin/flash-gui.sh"
|
||||
|
||||
if [ "$CONFIG_RESTRICTED_BOOT" = y ]; then
|
||||
whiptail $BG_COLOR_ERROR --title 'Restricted Boot Active' \
|
||||
--msgbox "Disable Restricted Boot to flash new firmware." 16 60
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while true; do
|
||||
unset menu_choice
|
||||
whiptail $BG_COLOR_MAIN_MENU --title "Firmware Management Menu" \
|
||||
|
@ -603,6 +603,10 @@ attempt_default_boot()
|
||||
force_unsafe_boot()
|
||||
{
|
||||
TRACE "Under /bin/gui-init:force_unsafe_boot"
|
||||
if [ "$CONFIG_RESTRICTED_BOOT" = y ]; then
|
||||
whiptail $BG_COLOR_ERROR --title 'ERROR: Restricted Boot Enabled' --msgbox "Restricted Boot is Enabled, forced boot not allowed.\n\nPress OK to return to the Main Menu" 0 80
|
||||
return
|
||||
fi
|
||||
# Run the menu selection in "force" mode, bypassing hash checks
|
||||
if (whiptail $BG_COLOR_WARNING --title 'Unsafe Forced Boot Selected!' \
|
||||
--yesno "WARNING: You have chosen to skip all tamper checks and boot anyway.\n\nThis is an unsafe option!\n\nDo you want to proceed?" 0 80) then
|
||||
|
@ -92,6 +92,10 @@ if [ `cat /tmp/iso_menu.txt | wc -l` -gt 0 ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$CONFIG_RESTRICTED_BOOT" = y ]; then
|
||||
die "ISO boot failed in Restricted Boot mode."
|
||||
fi
|
||||
|
||||
echo "!!! Could not find any ISO, trying bootable USB"
|
||||
# Attempt to pull verified config from device
|
||||
if [ -x /bin/whiptail ]; then
|
||||
|
@ -250,6 +250,32 @@ cleanup_shred() {
|
||||
shred -n 10 -z -u "$1" 2>/dev/null || true
|
||||
}
|
||||
|
||||
# tpm2_destroy: Destroy a sealed file in the TPM. The mechanism differs by
|
||||
# TPM version - TPM2 evicts the file object, so it no longer exists.
|
||||
tpm2_destroy() {
|
||||
index="$1" # Index of the sealed file
|
||||
size="$2" # Size of zeroes to overwrite for TPM1 (unused in TPM2)
|
||||
|
||||
# Pad with up to 6 zeros, i.e. '0x81000001', '0x81001234', etc.
|
||||
handle="$(printf "0x81%6s" "$index" | tr ' ' 0)"
|
||||
|
||||
# remove possible data occupying this handle
|
||||
tpm2 evictcontrol -Q -C p -c "$handle" 2>/dev/null \
|
||||
|| die "Unable to evict secret"
|
||||
}
|
||||
|
||||
# tpm1_destroy: Destroy a sealed file in the TPM. The mechanism differs by
|
||||
# TPM version - TPM1 overwrites the file with zeroes, since this can be done
|
||||
# without authorization. (Deletion requires authorization.)
|
||||
tpm1_destroy() {
|
||||
index="$1" # Index of the sealed file
|
||||
size="$2" # Size of zeroes to overwrite for TPM1
|
||||
|
||||
dd if=/dev/zero bs="$size" count=1 of=/tmp/wipe-totp-zero
|
||||
tpm nv_writevalue -in "$index" -if /tmp/wipe-totp-zero \
|
||||
|| die "Unable to wipe sealed secret"
|
||||
}
|
||||
|
||||
# tpm2_seal: Seal a file against PCR values and, optionally, a password.
|
||||
# If a password is given, both the PCRs and password are required to unseal the
|
||||
# file. PCRs are provided as a PCR list and data file. PCR data must be
|
||||
@ -576,6 +602,8 @@ if [ "$CONFIG_TPM2_TOOLS" != "y" ]; then
|
||||
echo "$PCR_SIZE";;
|
||||
calcfuturepcr)
|
||||
shift; tpm1_calcfuturepcr "$@";;
|
||||
destroy)
|
||||
shift; tpm1_destroy "$@";;
|
||||
seal)
|
||||
shift; tpm1_seal "$@";;
|
||||
startsession)
|
||||
@ -615,6 +643,8 @@ case "$subcmd" in
|
||||
tpm2_counter_inc "$@";;
|
||||
counter_create)
|
||||
tpm2_counter_cre "$@";;
|
||||
destroy)
|
||||
tpm2_destroy "$@";;
|
||||
seal)
|
||||
tpm2_seal "$@";;
|
||||
startsession)
|
||||
|
14
initrd/bin/wipe-totp
Executable file
14
initrd/bin/wipe-totp
Executable file
@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
# Wipe the sealed TOTP/HOTP secret. The secret is overwritten with all-0,
|
||||
# rather than deleted, because deletion requires authorization. Wiping the
|
||||
# secret will cause the next boot to prompt to regenerate the secret.
|
||||
|
||||
. /etc/functions
|
||||
|
||||
TPM_NVRAM_SPACE=4d47
|
||||
TPM_SIZE=312
|
||||
|
||||
if [ "$CONFIG_TPM" = "y" ]; then
|
||||
tpmr destroy "$TPM_NVRAM_SPACE" "$TPM_SIZE" \
|
||||
|| die "Unable to wipe sealed secret"
|
||||
fi
|
@ -62,6 +62,11 @@ recovery() {
|
||||
tpmr extend -ix 4 -ic recovery
|
||||
fi
|
||||
|
||||
if [ "$CONFIG_RESTRICTED_BOOT" = y ]; then
|
||||
echo >&2 "Restricted Boot enabled, recovery console disabled, rebooting in 5 seconds"
|
||||
sleep 5
|
||||
/bin/reboot
|
||||
fi
|
||||
while [ true ]
|
||||
do
|
||||
echo >&2 "!!!!! Starting recovery shell"
|
||||
|
Loading…
Reference in New Issue
Block a user