Merge pull request #1515 from tlaurion/inmemory_keygen-gpg_backup_usable_for_RSA_only-copy_to_card_working_for_RSA_only-gpg_auth_for_recovery_and_sub_boot

GPG User Authentication: In-memory gpg keygen + keytocard and GPG key material backup enabling  (plus a lot of code cleanup and UX improvements)
This commit is contained in:
tlaurion 2023-11-13 16:05:26 -05:00 committed by GitHub
commit 133da0e48e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 4885 additions and 1046 deletions

View File

@ -30,7 +30,6 @@ CONFIG_LINUX_USB=y
export CONFIG_TPM=y export CONFIG_TPM=y
export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y
export CONFIG_TOTP_SKIP_QRCODE=y export CONFIG_TOTP_SKIP_QRCODE=y
export CONFIG_OEMRESET_OFFER_DEFAULTS=y
export CONFIG_BOOTSCRIPT=/bin/gui-init export CONFIG_BOOTSCRIPT=/bin/gui-init
export CONFIG_BOOT_REQ_HASH=n export CONFIG_BOOT_REQ_HASH=n
export CONFIG_BOOT_REQ_ROLLBACK=n export CONFIG_BOOT_REQ_ROLLBACK=n

View File

@ -30,7 +30,6 @@ CONFIG_LINUX_USB=y
export CONFIG_TPM=y export CONFIG_TPM=y
export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y
export CONFIG_TOTP_SKIP_QRCODE=y export CONFIG_TOTP_SKIP_QRCODE=y
export CONFIG_OEMRESET_OFFER_DEFAULTS=y
export CONFIG_BOOTSCRIPT=/bin/gui-init export CONFIG_BOOTSCRIPT=/bin/gui-init
export CONFIG_BOOT_REQ_HASH=n export CONFIG_BOOT_REQ_HASH=n
export CONFIG_BOOT_REQ_ROLLBACK=n export CONFIG_BOOT_REQ_ROLLBACK=n

View File

@ -28,7 +28,6 @@ CONFIG_LINUX_USB=y
export CONFIG_TPM=y export CONFIG_TPM=y
export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y
export CONFIG_TOTP_SKIP_QRCODE=y export CONFIG_TOTP_SKIP_QRCODE=y
export CONFIG_OEMRESET_OFFER_DEFAULTS=y
export CONFIG_BOOTSCRIPT=/bin/gui-init export CONFIG_BOOTSCRIPT=/bin/gui-init
export CONFIG_BOOT_REQ_HASH=n export CONFIG_BOOT_REQ_HASH=n

View File

@ -30,7 +30,6 @@ CONFIG_LINUX_USB=y
export CONFIG_TPM=y export CONFIG_TPM=y
export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y
export CONFIG_TOTP_SKIP_QRCODE=y export CONFIG_TOTP_SKIP_QRCODE=y
export CONFIG_OEMRESET_OFFER_DEFAULTS=y
export CONFIG_BOOTSCRIPT=/bin/gui-init export CONFIG_BOOTSCRIPT=/bin/gui-init
export CONFIG_BOOT_REQ_HASH=n export CONFIG_BOOT_REQ_HASH=n
export CONFIG_BOOT_REQ_ROLLBACK=n export CONFIG_BOOT_REQ_ROLLBACK=n

View File

@ -31,7 +31,6 @@ CONFIG_LINUX_USB=y
export CONFIG_TPM=y export CONFIG_TPM=y
export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y
export CONFIG_TOTP_SKIP_QRCODE=y export CONFIG_TOTP_SKIP_QRCODE=y
export CONFIG_OEMRESET_OFFER_DEFAULTS=y
export CONFIG_BOOTSCRIPT=/bin/gui-init export CONFIG_BOOTSCRIPT=/bin/gui-init
export CONFIG_BOOT_REQ_HASH=n export CONFIG_BOOT_REQ_HASH=n
export CONFIG_BOOT_REQ_ROLLBACK=n export CONFIG_BOOT_REQ_ROLLBACK=n

View File

@ -29,7 +29,6 @@ CONFIG_LINUX_USB=y
export CONFIG_TPM=y export CONFIG_TPM=y
export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y
export CONFIG_TOTP_SKIP_QRCODE=y export CONFIG_TOTP_SKIP_QRCODE=y
export CONFIG_OEMRESET_OFFER_DEFAULTS=y
export CONFIG_BOOTSCRIPT=/bin/gui-init export CONFIG_BOOTSCRIPT=/bin/gui-init
export CONFIG_BOOT_REQ_HASH=n export CONFIG_BOOT_REQ_HASH=n

View File

@ -32,7 +32,6 @@ CONFIG_OPENSSL=y
CONFIG_PRIMARY_KEY_TYPE=ecc CONFIG_PRIMARY_KEY_TYPE=ecc
export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y
export CONFIG_TOTP_SKIP_QRCODE=y export CONFIG_TOTP_SKIP_QRCODE=y
export CONFIG_OEMRESET_OFFER_DEFAULTS=y
export CONFIG_BOOTSCRIPT=/bin/gui-init export CONFIG_BOOTSCRIPT=/bin/gui-init
export CONFIG_BOOT_REQ_HASH=n export CONFIG_BOOT_REQ_HASH=n

View File

@ -30,7 +30,6 @@ CONFIG_LINUX_USB=y
export CONFIG_TPM=n export CONFIG_TPM=n
export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y
export CONFIG_TOTP_SKIP_QRCODE=y export CONFIG_TOTP_SKIP_QRCODE=y
export CONFIG_OEMRESET_OFFER_DEFAULTS=y
export CONFIG_BOOTSCRIPT=/bin/gui-init export CONFIG_BOOTSCRIPT=/bin/gui-init
export CONFIG_BOOT_REQ_HASH=n export CONFIG_BOOT_REQ_HASH=n

View File

@ -30,7 +30,6 @@ CONFIG_LINUX_USB=y
export CONFIG_TPM=n export CONFIG_TPM=n
export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y export CONFIG_TPM_NO_LUKS_DISK_UNLOCK=y
export CONFIG_TOTP_SKIP_QRCODE=y export CONFIG_TOTP_SKIP_QRCODE=y
export CONFIG_OEMRESET_OFFER_DEFAULTS=y
export CONFIG_BOOTSCRIPT=/bin/gui-init export CONFIG_BOOTSCRIPT=/bin/gui-init
export CONFIG_BOOT_REQ_HASH=n export CONFIG_BOOT_REQ_HASH=n

View File

@ -41,9 +41,11 @@ Bootstrapping a working system
* Then Heads will indicate that there is no TOTP code yet, at this point shut down (Continue to main menu -> Power off) * Then Heads will indicate that there is no TOTP code yet, at this point shut down (Continue to main menu -> Power off)
5. Get the public key that was saved to the virtual USB flash drive 5. Get the public key that was saved to the virtual USB flash drive
* `sudo mkdir /media/fd_heads_gpg` * `sudo mkdir /media/fd_heads_gpg`
* `sudo mount ./build/x86/qemu-coreboot-fbwhiptail-tpm1-hotp/usb_fd.raw /media/fd_heads_gpg` * `sudo losetup --find --partscan ./build/x86/qemu-coreboot-fbwhiptail-tpm1-hotp/usb_fd.raw`
* `sudo mount /dev/loop0p2 /media/fd_heads_gpg` to mount the second partition (public) or if only one partition, /dev/loop0p1
* Look in `/media/fd_heads_gpg` and copy the most recent public key * Look in `/media/fd_heads_gpg` and copy the most recent public key
* `sudo umount /media/fd_heads_gpg` * `sudo umount /media/fd_heads_gpg`
* `sudo losetup --detach /dev/loop0`
6. Inject the GPG key into the Heads image and run again 6. Inject the GPG key into the Heads image and run again
* `make BOARD=qemu-coreboot-fbwhiptail-tpm1-hotp PUBKEY_ASC=<path_to_key.asc> inject_gpg` * `make BOARD=qemu-coreboot-fbwhiptail-tpm1-hotp PUBKEY_ASC=<path_to_key.asc> inject_gpg`
* `make BOARD=qemu-coreboot-fbwhiptail-tpm1-hotp USB_TOKEN=LibremKey PUBKEY_ASC=<path_to_key.asc> run` * `make BOARD=qemu-coreboot-fbwhiptail-tpm1-hotp USB_TOKEN=LibremKey PUBKEY_ASC=<path_to_key.asc> run`

View File

@ -10,6 +10,9 @@ export CONFIG_LINUX_VERSION=5.10.5
#export CONFIG_RESTRICTED_BOOT=y #export CONFIG_RESTRICTED_BOOT=y
#export CONFIG_BASIC=y #export CONFIG_BASIC=y
#Enable HAVE_GPG_KEY_BACKUP to test GPG key backup drive (we cannot inject config under QEMU (no internal flashing))
#export CONFIG_HAVE_GPG_KEY_BACKUP=y
#Enable DEBUG output #Enable DEBUG output
export CONFIG_DEBUG_OUTPUT=y export CONFIG_DEBUG_OUTPUT=y
export CONFIG_ENABLE_FUNCTION_TRACING_OUTPUT=y export CONFIG_ENABLE_FUNCTION_TRACING_OUTPUT=y

View File

@ -10,6 +10,9 @@ export CONFIG_LINUX_VERSION=5.10.5
#export CONFIG_RESTRICTED_BOOT=y #export CONFIG_RESTRICTED_BOOT=y
#export CONFIG_BASIC=y #export CONFIG_BASIC=y
#Enable HAVE_GPG_KEY_BACKUP to test GPG key backup drive (we cannot inject config under QEMU (no internal flashing))
#export CONFIG_HAVE_GPG_KEY_BACKUP=y
#Enable DEBUG output #Enable DEBUG output
export CONFIG_DEBUG_OUTPUT=y export CONFIG_DEBUG_OUTPUT=y
export CONFIG_ENABLE_FUNCTION_TRACING_OUTPUT=y export CONFIG_ENABLE_FUNCTION_TRACING_OUTPUT=y

View File

@ -6,10 +6,13 @@ export CONFIG_COREBOOT=y
export CONFIG_COREBOOT_VERSION=4.19 export CONFIG_COREBOOT_VERSION=4.19
export CONFIG_LINUX_VERSION=5.10.5 export CONFIG_LINUX_VERSION=5.10.5
#Enable only one RESTRICTED/BASIC boot modes below to test them manually (we cannot inject config under QEMU (no internal flashing) #Enable only one RESTRICTED/BASIC boot modes below to test them manually (we cannot inject config under QEMU (no internal flashing))
#export CONFIG_RESTRICTED_BOOT=y #export CONFIG_RESTRICTED_BOOT=y
#export CONFIG_BASIC=y #export CONFIG_BASIC=y
#Enable HAVE_GPG_KEY_BACKUP to test GPG key backup drive (we cannot inject config under QEMU (no internal flashing))
#export CONFIG_HAVE_GPG_KEY_BACKUP=y
#Enable DEBUG output #Enable DEBUG output
export CONFIG_DEBUG_OUTPUT=y export CONFIG_DEBUG_OUTPUT=y
export CONFIG_ENABLE_FUNCTION_TRACING_OUTPUT=y export CONFIG_ENABLE_FUNCTION_TRACING_OUTPUT=y

View File

@ -10,6 +10,9 @@ export CONFIG_LINUX_VERSION=5.10.5
#export CONFIG_RESTRICTED_BOOT=y #export CONFIG_RESTRICTED_BOOT=y
#export CONFIG_BASIC=y #export CONFIG_BASIC=y
#Enable HAVE_GPG_KEY_BACKUP to test GPG key backup drive (we cannot inject config under QEMU (no internal flashing))
#export CONFIG_HAVE_GPG_KEY_BACKUP=y
#Enable DEBUG output #Enable DEBUG output
export CONFIG_DEBUG_OUTPUT=y export CONFIG_DEBUG_OUTPUT=y
export CONFIG_ENABLE_FUNCTION_TRACING_OUTPUT=y export CONFIG_ENABLE_FUNCTION_TRACING_OUTPUT=y

File diff suppressed because it is too large Load Diff

View File

@ -1548,7 +1548,7 @@ CONFIG_DEVPORT=y
# CONFIG_HPET is not set # CONFIG_HPET is not set
# CONFIG_HANGCHECK_TIMER is not set # CONFIG_HANGCHECK_TIMER is not set
CONFIG_TCG_TPM=y CONFIG_TCG_TPM=y
CONFIG_HW_RANDOM_TPM=n # CONFIG_HW_RANDOM_TPM is not set
CONFIG_TCG_TIS_CORE=y CONFIG_TCG_TIS_CORE=y
CONFIG_TCG_TIS=y CONFIG_TCG_TIS=y
# CONFIG_TCG_TIS_I2C is not set # CONFIG_TCG_TIS_I2C is not set
@ -2768,7 +2768,8 @@ CONFIG_VFAT_FS=y
CONFIG_FAT_DEFAULT_CODEPAGE=437 CONFIG_FAT_DEFAULT_CODEPAGE=437
CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
# CONFIG_FAT_DEFAULT_UTF8 is not set # CONFIG_FAT_DEFAULT_UTF8 is not set
# CONFIG_EXFAT_FS is not set CONFIG_EXFAT_FS=y
CONFIG_EXFAT_DEFAULT_IOCHARSET="utf8"
# CONFIG_NTFS_FS is not set # CONFIG_NTFS_FS is not set
# CONFIG_NTFS3_FS is not set # CONFIG_NTFS3_FS is not set
# end of DOS/FAT/EXFAT/NT Filesystems # end of DOS/FAT/EXFAT/NT Filesystems

View File

@ -1,3 +1,7 @@
#mount /boot in read-only by default
mount /boot
#verify detached signature of /boot content
find /boot/kexec*.txt | gpg --verify /boot/kexec.sig -
#remove invalid kexec_* signed files #remove invalid kexec_* signed files
mount /dev/sda1 /boot && mount -o remount,rw /boot && rm /boot/kexec* && mount -o remount,ro /boot mount /dev/sda1 /boot && mount -o remount,rw /boot && rm /boot/kexec* && mount -o remount,ro /boot
#Generate keys from GPG smartcard: #Generate keys from GPG smartcard:

View File

@ -24,6 +24,7 @@ for cbfsname in `echo $cbfsfiles`; do
TMPFILE=/tmp/cbfs.$$ TMPFILE=/tmp/cbfs.$$
echo "$filename" > $TMPFILE echo "$filename" > $TMPFILE
cat $filename >> $TMPFILE cat $filename >> $TMPFILE
DEBUG "Extending TPM PCR $CONFIG_PCR with $filename"
tpmr extend -ix "$CONFIG_PCR" -if $TMPFILE \ tpmr extend -ix "$CONFIG_PCR" -if $TMPFILE \
|| die "$filename: tpm extend failed" || die "$filename: tpm extend failed"
fi fi

View File

@ -151,12 +151,12 @@ prompt_update_checksums()
generate_totp_hotp() generate_totp_hotp()
{ {
tpm_password="$1" # May be empty, will prompt if needed and empty
TRACE "Under /bin/gui-init:generate_totp_hotp" TRACE "Under /bin/gui-init:generate_totp_hotp"
tpm_owner_password="$1" # May be empty, will prompt if needed and empty
if [ "$CONFIG_TPM" != "y" ] && [ -x /bin/hotp_verification ]; then if [ "$CONFIG_TPM" != "y" ] && [ -x /bin/hotp_verification ]; then
echo "Generating new HOTP secret" echo "Generating new HOTP secret"
/bin/seal-hotpkey /bin/seal-hotpkey
elif echo -e "Generating new TOTP secret...\n\n" && /bin/seal-totp "$BOARD_NAME" "$tpm_password"; then elif echo -e "Generating new TOTP secret...\n\n" && /bin/seal-totp "$BOARD_NAME" "$tpm_owner_password"; then
echo echo
if [ -x /bin/hotp_verification ]; then if [ -x /bin/hotp_verification ]; then
if [ "$CONFIG_TOTP_SKIP_QRCODE" != y ]; then if [ "$CONFIG_TOTP_SKIP_QRCODE" != y ]; then
@ -229,8 +229,7 @@ update_totp()
g ) g )
if (whiptail $BG_COLOR_WARNING --title 'Generate new TOTP/HOTP secret' \ if (whiptail $BG_COLOR_WARNING --title 'Generate new TOTP/HOTP secret' \
--yesno "This will erase your old secret and replace it with a new one!\n\nDo you want to proceed?" 0 80) then --yesno "This will erase your old secret and replace it with a new one!\n\nDo you want to proceed?" 0 80) then
generate_totp_hotp && update_totp && BG_COLOR_MAIN_MENU="" generate_totp_hotp && update_totp && BG_COLOR_MAIN_MENU="" && reseal_tpm_disk_decryption_key
reseal_tpm_disk_decryption_key
fi fi
;; ;;
i ) i )
@ -238,8 +237,7 @@ update_totp()
return 1 return 1
;; ;;
p ) p )
reset_tpm && update_totp && BG_COLOR_MAIN_MENU="" reset_tpm && update_totp && BG_COLOR_MAIN_MENU="" && reseal_tpm_disk_decryption_key
reseal_tpm_disk_decryption_key
;; ;;
x ) x )
recovery "User requested recovery shell" recovery "User requested recovery shell"
@ -300,8 +298,7 @@ update_hotp()
g ) g )
if (whiptail $BG_COLOR_WARNING --title 'Generate new TOTP/HOTP secret' \ if (whiptail $BG_COLOR_WARNING --title 'Generate new TOTP/HOTP secret' \
--yesno "This will erase your old secret and replace it with a new one!\n\nDo you want to proceed?" 0 80) then --yesno "This will erase your old secret and replace it with a new one!\n\nDo you want to proceed?" 0 80) then
generate_totp_hotp && BG_COLOR_MAIN_MENU="" generate_totp_hotp && BG_COLOR_MAIN_MENU="" && reseal_tpm_disk_decryption_key
reseal_tpm_disk_decryption_key
fi fi
;; ;;
i ) i )
@ -316,7 +313,7 @@ update_hotp()
clean_boot_check() clean_boot_check()
{ {
TRACE "Under /bin/gui-init:mount_boot" TRACE "Under /bin/gui-init:clean_boot_check"
# assume /boot mounted # assume /boot mounted
if ! grep -q /boot /proc/mounts ; then if ! grep -q /boot /proc/mounts ; then
return return
@ -526,12 +523,10 @@ show_tpm_totp_hotp_options_menu()
option=$(cat /tmp/whiptail) option=$(cat /tmp/whiptail)
case "$option" in case "$option" in
g ) g )
generate_totp_hotp generate_totp_hotp && reseal_tpm_disk_decryption_key
reseal_tpm_disk_decryption_key
;; ;;
r ) r )
reset_tpm reset_tpm && reseal_tpm_disk_decryption_key
reseal_tpm_disk_decryption_key
;; ;;
t ) t )
prompt_totp_mismatch prompt_totp_mismatch
@ -572,7 +567,7 @@ reset_tpm()
return 1 return 1
fi fi
tpmr reset "$key_password" tpmr reset "$tpm_owner_password"
# now that the TPM is reset, remove invalid TPM counter files # now that the TPM is reset, remove invalid TPM counter files
mount_boot mount_boot
@ -582,7 +577,7 @@ reset_tpm()
rm -f /boot/kexec_primhdl_hash.txt rm -f /boot/kexec_primhdl_hash.txt
# create Heads TPM counter before any others # create Heads TPM counter before any others
check_tpm_counter /boot/kexec_rollback.txt "" "$key_password" \ check_tpm_counter /boot/kexec_rollback.txt "" "$tpm_owner_password" \
|| die "Unable to find/create tpm counter" || die "Unable to find/create tpm counter"
counter="$TPM_COUNTER" counter="$TPM_COUNTER"
@ -593,7 +588,7 @@ reset_tpm()
|| die "Unable to create rollback file" || die "Unable to create rollback file"
mount -o ro,remount /boot mount -o ro,remount /boot
generate_totp_hotp "$key_password" generate_totp_hotp "$tpm_owner_password"
else else
echo "Returning to the main menu" echo "Returning to the main menu"
fi fi

View File

@ -49,6 +49,7 @@ if ! kexec-unseal-key "$INITRD_DIR/secret.key"; then
fi fi
# Override PCR 4 so that user can't read the key # Override PCR 4 so that user can't read the key
DEBUG "Extending TPM PCR 4 to prevent further secret unsealing"
tpmr extend -ix 4 -ic generic || tpmr extend -ix 4 -ic generic ||
die 'Unable to scramble PCR' die 'Unable to scramble PCR'
@ -92,7 +93,6 @@ if [ "$unseal_failed" = "n" ]; then
done done
else else
# No crypttab files were found under selected default boot option's initrd file # No crypttab files were found under selected default boot option's initrd file
# TODO: cpio -t is unfit here :( it just extracts early cpio header and not the whole file. Replace with something else
# Meanwhile, force crypttab to be created from scratch on both possible locations: /etc/crypttab and /cryptroot/crypttab # Meanwhile, force crypttab to be created from scratch on both possible locations: /etc/crypttab and /cryptroot/crypttab
crypttab_files="etc/crypttab cryptroot/crypttab" crypttab_files="etc/crypttab cryptroot/crypttab"
for crypttab_file in $crypttab_files; do for crypttab_file in $crypttab_files; do

View File

@ -276,8 +276,9 @@ if [ ! -d $paramsdir ]; then
fi fi
if [ "$CONFIG_TPM2_TOOLS" = "y" ]; then if [ "$CONFIG_TPM2_TOOLS" = "y" ]; then
sha256sum /tmp/primary.handle >"$PRIMHASH_FILE" || sha256sum /tmp/secret/primary.handle >"$PRIMHASH_FILE" ||
die "ERROR: Failed to Hash TPM2 primary key handle!" die "ERROR: Failed to Hash TPM2 primary key handle!"
DEBUG "TPM2 primary key handle hash saved to $PRIMHASH_FILE"
fi fi
rm $paramsdir/kexec_default.*.txt 2>/dev/null || true rm $paramsdir/kexec_default.*.txt 2>/dev/null || true

View File

@ -42,7 +42,6 @@ DEBUG "kexec-save-key prior of last override: paramsdir: $paramsdir, paramsdev:
if [ -n "$lvm_volume_group" ]; then if [ -n "$lvm_volume_group" ]; then
lvm vgchange -a y $lvm_volume_group || lvm vgchange -a y $lvm_volume_group ||
die "Failed to activate the LVM group" die "Failed to activate the LVM group"
#TODO: why reuse key_devices for lvm devices?
for dev in /dev/$lvm_volume_group/*; do for dev in /dev/$lvm_volume_group/*; do
key_devices="$key_devices $dev" key_devices="$key_devices $dev"
done done

View File

@ -72,20 +72,21 @@ dd \
# Count the number of slots used on each device # Count the number of slots used on each device
for dev in $(cat "$KEY_DEVICES" | cut -d\ -f1); do for dev in $(cat "$KEY_DEVICES" | cut -d\ -f1); do
DEBUG "Checking number of slots used on $dev" DEBUG "Checking number of slots used on $dev LUKS header"
#check if the device is a LUKS device with luks[1,2] #check if the device is a LUKS device with luks[1,2]
slots_used=$(cryptsetup luksDump $dev | grep -c 'luks[0-9]*' || die "Unable to get number of slots used on $dev") slots_used=$(cryptsetup luksDump $dev | grep -c 'luks[0-9]*' || die "Unable to get number of slots used on $dev")
DEBUG "Number of slots used on $dev: $slots_used" DEBUG "Number of slots used on $dev LUKS header: $slots_used"
# If slot1 is the only one used, warn and die with proper messages # If slot1 is the only one used, warn and die with proper messages
if [ $slots_used -eq 1 ]; then if [ $slots_used -eq 1 ]; then
# Check if slot 1 is the only one existing # Check if slot 1 is the only one existing
if cryptsetup luksDump $dev | grep -q "Slot 1: ENABLED"; then if cryptsetup luksDump $dev | grep -q "Slot 1: ENABLED"; then
warn "Slot 1 is the only one existing on $dev. Heads cannot use it to store TPM sealed LUKS Disk Unlock Key" warn "Slot 1 is the only one existing on $dev LUKS header. Heads cannot use it to store TPM sealed LUKS Disk Unlock Key"
die "Slot 1 should not be the only slot existing on $dev. Fix your custom setup" warn "Slot 1 should not be the only slot existing on $dev LUKS header. Slot 0 should be used to store Disk Recovery Key/passphrase"
die "You can safely fix this before continuing through Heads recovery shell: cryptsetup luksAddKey $dev"
fi fi
else else
DEBUG "Slot 1 is not the only existing slot on $dev" DEBUG "Slot 1 is not the only existing slot on $dev LUKS header."
DEBUG "$dev Slot 1 will be used to store LUKS Disk Unlock Key that TPM will seal/unseal with TPM Disk Unlock Key passphrase" DEBUG "$dev LUKS header's slot 1 will store LUKS Disk Unlock Key that TPM will seal/unseal with TPM Disk Unlock Key passphrase"
fi fi
done done
@ -136,7 +137,7 @@ tpmr pcrread -a 7 "$pcrf"
DO_WITH_DEBUG --mask-position 7 \ DO_WITH_DEBUG --mask-position 7 \
tpmr seal "$KEY_FILE" "$TPM_INDEX" 0,1,2,3,4,5,6,7 "$pcrf" \ tpmr seal "$KEY_FILE" "$TPM_INDEX" 0,1,2,3,4,5,6,7 "$pcrf" \
"$TPM_SIZE" "$key_password" "$TPM_SIZE" "$key_password" || die "Unable to write TPM Disk Unlock Key to NVRAM"
# should be okay if this fails # should be okay if this fails
shred -n 10 -z -u "$pcrf" 2>/dev/null || shred -n 10 -z -u "$pcrf" 2>/dev/null ||
@ -144,7 +145,7 @@ shred -n 10 -z -u "$pcrf" 2>/dev/null ||
shred -n 10 -z -u "$KEY_FILE" 2>/dev/null || shred -n 10 -z -u "$KEY_FILE" 2>/dev/null ||
warn "Failed to delete key file - continuing" warn "Failed to delete key file - continuing"
mount -o rw,remount $paramsdir || die "Failed to remount $paramsdir in RW - continuing" mount -o rw,remount $paramsdir || warn "Failed to remount $paramsdir in RW - continuing"
cp -f /tmp/luksDump.txt "$paramsdir/kexec_lukshdr_hash.txt" || cp -f /tmp/luksDump.txt "$paramsdir/kexec_lukshdr_hash.txt" ||
die "Failed to copy LUKS header hashes to /boot - continuing" warn "Failed to copy LUKS header hashes to /boot - continuing"
mount -o ro,remount $paramsdir || die "Failed to remount $paramsdir in RO - continuing" mount -o ro,remount $paramsdir || warn "Failed to remount $paramsdir in RO - continuing"

View File

@ -19,18 +19,25 @@ force_boot="n"
skip_confirm="n" skip_confirm="n"
while getopts "b:d:p:a:r:c:uimgfs" arg; do while getopts "b:d:p:a:r:c:uimgfs" arg; do
case $arg in case $arg in
b) bootdir="$OPTARG" ;; b) bootdir="$OPTARG" ;;
d) paramsdev="$OPTARG" ;; d) paramsdev="$OPTARG" ;;
p) paramsdir="$OPTARG" ;; p) paramsdir="$OPTARG" ;;
a) add="$OPTARG" ;; a) add="$OPTARG" ;;
r) remove="$OPTARG" ;; r) remove="$OPTARG" ;;
c) config="$OPTARG" ;; c) config="$OPTARG" ;;
u) unique="y" ;; u) unique="y" ;;
m) force_menu="y" ;; m) force_menu="y" ;;
i) valid_hash="y"; valid_rollback="y" ;; i)
g) gui_menu="y" ;; valid_hash="y"
f) force_boot="y"; valid_hash="y"; valid_rollback="y" ;; valid_rollback="y"
s) skip_confirm="y" ;; ;;
g) gui_menu="y" ;;
f)
force_boot="y"
valid_hash="y"
valid_rollback="y"
;;
s) skip_confirm="y" ;;
esac esac
done done
@ -53,24 +60,25 @@ paramsdir="${paramsdir%%/}"
PRIMHASH_FILE="$paramsdir/kexec_primhdl_hash.txt" PRIMHASH_FILE="$paramsdir/kexec_primhdl_hash.txt"
if [ "$CONFIG_TPM2_TOOLS" = "y" ]; then if [ "$CONFIG_TPM2_TOOLS" = "y" ]; then
if [ -r "$PRIMHASH_FILE" ]; then if [ -r "$PRIMHASH_FILE" ]; then
sha256sum -c "$PRIMHASH_FILE" \ sha256sum -c "$PRIMHASH_FILE" ||
|| { {
echo "FATAL: Hash of TPM2 primary key handle mismatch!"; echo "FATAL: Hash of TPM2 primary key handle mismatch!"
warn "If you have not intentionally regenerated TPM2 primary key,"; warn "If you have not intentionally regenerated TPM2 primary key,"
warn "your system may have been compromised"; warn "your system may have been compromised"
} DEBUG "Hash of TPM2 primary key handle mismatched for $PRIMHASH_FILE"
}
else else
warn "Hash of TPM2 primary key handle does not exist" warn "Hash of TPM2 primary key handle does not exist"
warn "Please rebuild the boot hash tree" warn "Please rebuild the boot hash tree"
default_failed="y" default_failed="y"
DEBUG "Hash of TPM2 primary key handle does not exist under $PRIMHASH_FILE"
fi fi
fi fi
verify_global_hashes() verify_global_hashes() {
{
echo "+++ Checking verified boot hash file " echo "+++ Checking verified boot hash file "
# Check the hashes of all the files # Check the hashes of all the files
if verify_checksums "$bootdir" "$gui_menu" ; then if verify_checksums "$bootdir" "$gui_menu"; then
echo "+++ Verified boot hashes " echo "+++ Verified boot hashes "
valid_hash='y' valid_hash='y'
valid_global_hash='y' valid_global_hash='y'
@ -82,44 +90,43 @@ verify_global_hashes()
fi fi
die "$TMP_HASH_FILE: boot hash mismatch" die "$TMP_HASH_FILE: boot hash mismatch"
fi fi
# If user enables it, check root hashes before boot as well # If user enables it, check root hashes before boot as well
if [[ "$CONFIG_ROOT_CHECK_AT_BOOT" = "y" && "$force_menu" == "n" ]]; then if [[ "$CONFIG_ROOT_CHECK_AT_BOOT" = "y" && "$force_menu" == "n" ]]; then
if root-hashes-gui.sh -c; then if root-hashes-gui.sh -c; then
echo "+++ Verified root hashes, continuing boot " echo "+++ Verified root hashes, continuing boot "
# if user re-signs, it wipes out saved options, so scan the boot directory and generate # if user re-signs, it wipes out saved options, so scan the boot directory and generate
if [ ! -r "$TMP_MENU_FILE" ]; then if [ ! -r "$TMP_MENU_FILE" ]; then
scan_options scan_options
fi fi
else else
# root-hashes-gui.sh handles the GUI error menu, just die here # root-hashes-gui.sh handles the GUI error menu, just die here
if [ "$gui_menu" = "y" ]; then if [ "$gui_menu" = "y" ]; then
whiptail $BG_COLOR_ERROR --title 'ERROR: Root Hash Mismatch' \ whiptail $BG_COLOR_ERROR --title 'ERROR: Root Hash Mismatch' \
--msgbox "The root hash check failed!\nExiting to a recovery shell" 0 80 --msgbox "The root hash check failed!\nExiting to a recovery shell" 0 80
fi fi
die "root hash mismatch, see /tmp/hash_output_mismatches for details" die "root hash mismatch, see /tmp/hash_output_mismatches for details"
fi fi
fi fi
} }
verify_rollback_counter() verify_rollback_counter() {
{ TPM_COUNTER=$(grep counter $TMP_ROLLBACK_FILE | cut -d- -f2)
TPM_COUNTER=`grep counter $TMP_ROLLBACK_FILE | cut -d- -f2`
if [ -z "$TPM_COUNTER" ]; then if [ -z "$TPM_COUNTER" ]; then
die "$TMP_ROLLBACK_FILE: TPM counter not found?" die "$TMP_ROLLBACK_FILE: TPM counter not found?"
fi fi
read_tpm_counter $TPM_COUNTER \ read_tpm_counter $TPM_COUNTER ||
|| die "Failed to read TPM counter" die "Failed to read TPM counter"
sha256sum -c $TMP_ROLLBACK_FILE \ sha256sum -c $TMP_ROLLBACK_FILE ||
|| die "Invalid TPM counter state" die "Invalid TPM counter state"
valid_rollback="y" valid_rollback="y"
} }
first_menu="y" first_menu="y"
get_menu_option() { get_menu_option() {
num_options=`cat $TMP_MENU_FILE | wc -l` num_options=$(cat $TMP_MENU_FILE | wc -l)
if [ $num_options -eq 0 ]; then if [ $num_options -eq 0 ]; then
die "No boot options" die "No boot options"
fi fi
@ -129,13 +136,12 @@ get_menu_option() {
elif [ "$gui_menu" = "y" ]; then elif [ "$gui_menu" = "y" ]; then
MENU_OPTIONS="" MENU_OPTIONS=""
n=0 n=0
while read option while read option; do
do
parse_option parse_option
n=`expr $n + 1` n=$(expr $n + 1)
name=$(echo $name | tr " " "_") name=$(echo $name | tr " " "_")
MENU_OPTIONS="$MENU_OPTIONS $n ${name} " MENU_OPTIONS="$MENU_OPTIONS $n ${name} "
done < $TMP_MENU_FILE done <$TMP_MENU_FILE
whiptail --title "Select your boot option" \ whiptail --title "Select your boot option" \
--menu "Choose the boot option [1-$n, a to abort]:" 0 80 8 \ --menu "Choose the boot option [1-$n, a to abort]:" 0 80 8 \
@ -146,12 +152,11 @@ get_menu_option() {
else else
echo "+++ Select your boot option:" echo "+++ Select your boot option:"
n=0 n=0
while read option while read option; do
do
parse_option parse_option
n=`expr $n + 1` n=$(expr $n + 1)
echo "$n. $name [$kernel]" echo "$n. $name [$kernel]"
done < $TMP_MENU_FILE done <$TMP_MENU_FILE
read \ read \
-p "Choose the boot option [1-$n, a to abort]: " \ -p "Choose the boot option [1-$n, a to abort]: " \
@ -163,7 +168,7 @@ get_menu_option() {
fi fi
first_menu="n" first_menu="n"
option=`head -n $option_index $TMP_MENU_FILE | tail -1` option=$(head -n $option_index $TMP_MENU_FILE | tail -1)
parse_option parse_option
} }
@ -172,7 +177,7 @@ confirm_menu_option() {
default_text="Make default" default_text="Make default"
[[ "$CONFIG_TPM_NO_LUKS_DISK_UNLOCK" = "y" ]] && default_text="${default_text} and boot" [[ "$CONFIG_TPM_NO_LUKS_DISK_UNLOCK" = "y" ]] && default_text="${default_text} and boot"
whiptail $BG_COLOR_WARNING --title "Confirm boot details" \ whiptail $BG_COLOR_WARNING --title "Confirm boot details" \
--menu "Confirm the boot details for $name:\n\n$(echo $kernel| fold -s -w 80) \n\n" 0 80 8 \ --menu "Confirm the boot details for $name:\n\n$(echo $kernel | fold -s -w 80) \n\n" 0 80 8 \
-- 'd' "${default_text}" 'y' "Boot one time" \ -- 'd' "${default_text}" 'y' "Boot one time" \
2>/tmp/whiptail || die "Aborting boot attempt" 2>/tmp/whiptail || die "Aborting boot attempt"
@ -190,8 +195,8 @@ confirm_menu_option() {
} }
parse_option() { parse_option() {
name=`echo $option | cut -d\| -f1` name=$(echo $option | cut -d\| -f1)
kernel=`echo $option | cut -d\| -f3` kernel=$(echo $option | cut -d\| -f3)
} }
scan_options() { scan_options() {
@ -202,7 +207,7 @@ scan_options() {
die "Failed to parse any boot options" die "Failed to parse any boot options"
fi fi
if [ "$unique" = 'y' ]; then if [ "$unique" = 'y' ]; then
sort -r $option_file | uniq > $TMP_MENU_FILE sort -r $option_file | uniq >$TMP_MENU_FILE
else else
cp $option_file $TMP_MENU_FILE cp $option_file $TMP_MENU_FILE
fi fi
@ -224,7 +229,7 @@ save_default_option() {
-d "$paramsdev" \ -d "$paramsdev" \
-p "$paramsdir" \ -p "$paramsdir" \
-i "$option_index" \ -i "$option_index" \
; then ; then
echo "+++ Saved defaults to device" echo "+++ Saved defaults to device"
sleep 2 sleep 2
default_failed="n" default_failed="n"
@ -242,11 +247,11 @@ default_select() {
# Attempt boot with expected parameters # Attempt boot with expected parameters
# Check that entry matches that which is expected from menu # Check that entry matches that which is expected from menu
default_index=`basename "$TMP_DEFAULT_FILE" | cut -d. -f 2` default_index=$(basename "$TMP_DEFAULT_FILE" | cut -d. -f 2)
# Check to see if entries have changed - useful for detecting grub update # Check to see if entries have changed - useful for detecting grub update
expectedoption=`cat $TMP_DEFAULT_FILE` expectedoption=$(cat $TMP_DEFAULT_FILE)
option=`head -n $default_index $TMP_MENU_FILE | tail -1` option=$(head -n $default_index $TMP_MENU_FILE | tail -1)
if [ "$option" != "$expectedoption" ]; then if [ "$option" != "$expectedoption" ]; then
if [ "$gui_menu" = "y" ]; then if [ "$gui_menu" = "y" ]; then
whiptail $BG_COLOR_ERROR --title 'ERROR: Boot Entry Has Changed' \ whiptail $BG_COLOR_ERROR --title 'ERROR: Boot Entry Has Changed' \
@ -261,7 +266,7 @@ default_select() {
# Enforce that default option hashes are valid # Enforce that default option hashes are valid
echo "+++ Checking verified default boot hash file " echo "+++ Checking verified default boot hash file "
# Check the hashes of all the files # Check the hashes of all the files
if ( cd $bootdir && sha256sum -c "$TMP_DEFAULT_HASH_FILE" > /tmp/hash_output ); then if (cd $bootdir && sha256sum -c "$TMP_DEFAULT_HASH_FILE" >/tmp/hash_output); then
echo "+++ Verified default boot hashes " echo "+++ Verified default boot hashes "
valid_hash='y' valid_hash='y'
else else
@ -282,10 +287,9 @@ user_select() {
# No default expected boot parameters, ask user # No default expected boot parameters, ask user
option_confirm="" option_confirm=""
while [ "$option_confirm" != "y" -a "$option_confirm" != "d" ] while [ "$option_confirm" != "y" -a "$option_confirm" != "d" ]; do
do
get_menu_option get_menu_option
# In force boot mode, no need offer the option to set a default, just boot # In force boot mode, no need offer the option to set a default, just boot
if [[ "$force_boot" = "y" || "$skip_confirm" = "y" ]]; then if [[ "$force_boot" = "y" || "$skip_confirm" = "y" ]]; then
do_boot do_boot
else else
@ -305,8 +309,8 @@ user_select() {
echo "+++ Rebooting to start the new default option" echo "+++ Rebooting to start the new default option"
sleep 2 sleep 2
if [ "$CONFIG_DEBUG_OUTPUT" != "y" ]; then if [ "$CONFIG_DEBUG_OUTPUT" != "y" ]; then
reboot \ reboot ||
|| die "!!! Failed to reboot system" die "!!! Failed to reboot system"
else else
DEBUG "Rebooting is required prior of booting default boot entry" DEBUG "Rebooting is required prior of booting default boot entry"
# Instead of rebooting, drop to a recovery shell # Instead of rebooting, drop to a recovery shell
@ -319,8 +323,7 @@ user_select() {
do_boot do_boot
} }
do_boot() do_boot() {
{
if [ "$CONFIG_BASIC" != y ] && [ "$CONFIG_BOOT_REQ_ROLLBACK" = "y" ] && [ "$valid_rollback" = "n" ]; then if [ "$CONFIG_BASIC" != y ] && [ "$CONFIG_BOOT_REQ_ROLLBACK" = "y" ] && [ "$valid_rollback" = "n" ]; then
die "!!! Missing required rollback counter state" die "!!! Missing required rollback counter state"
fi fi
@ -330,31 +333,31 @@ do_boot()
fi fi
if [ "$CONFIG_BASIC" != y ] && [ "$CONFIG_TPM" = "y" ] && [ -r "$TMP_KEY_DEVICES" ]; then if [ "$CONFIG_BASIC" != y ] && [ "$CONFIG_TPM" = "y" ] && [ -r "$TMP_KEY_DEVICES" ]; then
INITRD=`kexec-boot -b "$bootdir" -e "$option" -i` \ INITRD=$(kexec-boot -b "$bootdir" -e "$option" -i) ||
|| die "!!! Failed to extract the initrd from boot option" die "!!! Failed to extract the initrd from boot option"
if [ -z "$INITRD" ]; then if [ -z "$INITRD" ]; then
die "!!! No initrd file found in boot option" die "!!! No initrd file found in boot option"
fi fi
kexec-insert-key $INITRD \ kexec-insert-key $INITRD ||
|| die "!!! Failed to insert disk key into a new initrd" die "!!! Failed to insert disk key into a new initrd"
kexec-boot -b "$bootdir" -e "$option" \ kexec-boot -b "$bootdir" -e "$option" \
-a "$add" -r "$remove" -o "/tmp/secret/initrd.cpio" \ -a "$add" -r "$remove" -o "/tmp/secret/initrd.cpio" ||
|| die "!!! Failed to boot w/ options: $option" die "!!! Failed to boot w/ options: $option"
else else
kexec-boot -b "$bootdir" -e "$option" -a "$add" -r "$remove" \ kexec-boot -b "$bootdir" -e "$option" -a "$add" -r "$remove" ||
|| die "!!! Failed to boot w/ options: $option" die "!!! Failed to boot w/ options: $option"
fi fi
} }
while true; do while true; do
if [ "$force_boot" = "y" -o "$CONFIG_BASIC" = "y" ]; then if [ "$force_boot" = "y" -o "$CONFIG_BASIC" = "y" ]; then
check_config $paramsdir force check_config $paramsdir force
else else
check_config $paramsdir check_config $paramsdir
fi fi
TMP_DEFAULT_FILE=`find /tmp/kexec/kexec_default.*.txt 2>/dev/null | head -1` || true TMP_DEFAULT_FILE=$(find /tmp/kexec/kexec_default.*.txt 2>/dev/null | head -1) || true
TMP_MENU_FILE="/tmp/kexec/kexec_menu.txt" TMP_MENU_FILE="/tmp/kexec/kexec_menu.txt"
TMP_HASH_FILE="/tmp/kexec/kexec_hashes.txt" TMP_HASH_FILE="/tmp/kexec/kexec_hashes.txt"
TMP_TREE_FILE="/tmp/kexec/kexec_tree.txt" TMP_TREE_FILE="/tmp/kexec/kexec_tree.txt"
@ -363,8 +366,8 @@ while true; do
TMP_KEY_DEVICES="/tmp/kexec/kexec_key_devices.txt" TMP_KEY_DEVICES="/tmp/kexec/kexec_key_devices.txt"
TMP_KEY_LVM="/tmp/kexec/kexec_key_lvm.txt" TMP_KEY_LVM="/tmp/kexec/kexec_key_lvm.txt"
# Allow a way for users to ignore warnings and boot into their systems # Allow a way for users to ignore warnings and boot into their systems
# even if hashes don't match # even if hashes don't match
if [ "$force_boot" = "y" ]; then if [ "$force_boot" = "y" ]; then
scan_options scan_options
if [ "$CONFIG_BASIC" != "y" ]; then if [ "$CONFIG_BASIC" != "y" ]; then
@ -378,8 +381,9 @@ while true; do
if [ "$CONFIG_TPM" = "y" ]; then if [ "$CONFIG_TPM" = "y" ]; then
if [ ! -r "$TMP_KEY_DEVICES" ]; then if [ ! -r "$TMP_KEY_DEVICES" ]; then
# Extend PCR4 as soon as possible # Extend PCR4 as soon as possible
tpmr extend -ix 4 -ic generic \ DEBUG "Extending TPM PCR 4 to prevent further secret unsealing"
|| die "Failed to extend PCR 4" tpmr extend -ix 4 -ic generic ||
die "Failed to extend PCR 4"
fi fi
fi fi
@ -412,7 +416,7 @@ while true; do
-a "$force_menu" = "n" \ -a "$force_menu" = "n" \
-a -r "$TMP_DEFAULT_FILE" \ -a -r "$TMP_DEFAULT_FILE" \
-a -r "$TMP_DEFAULT_HASH_FILE" ] \ -a -r "$TMP_DEFAULT_HASH_FILE" ] \
; then ; then
default_select default_select
default_failed="y" default_failed="y"
else else

View File

@ -7,6 +7,9 @@ set -e -o pipefail
TRACE "Under /bin/media-scan" TRACE "Under /bin/media-scan"
#Booting from external media should be authenticated if supported
gpg_auth || die "GPG authentication failed"
# Unmount any previous boot device # Unmount any previous boot device
if grep -q /boot /proc/mounts ; then if grep -q /boot /proc/mounts ; then
umount /boot \ umount /boot \

View File

@ -184,7 +184,7 @@ if cryptsetup isLuks "$USB_MOUNT_DEVICE"; then
|| die "ERROR: Failed to open ${USB_MOUNT_DEVICE} LUKS device" || die "ERROR: Failed to open ${USB_MOUNT_DEVICE} LUKS device"
fi fi
warn "Note that you cannot boot from a mounted encrypted device." warn "Note that you cannot boot from a mounted encrypted device"
DEBUG "Setting USB_MOUNT_DEVICE=/dev/mapper/"usb_mount_$(basename "$USB_MOUNT_DEVICE")"" DEBUG "Setting USB_MOUNT_DEVICE=/dev/mapper/"usb_mount_$(basename "$USB_MOUNT_DEVICE")""
USB_MOUNT_DEVICE="/dev/mapper/"usb_mount_$(basename "$USB_MOUNT_DEVICE")"" USB_MOUNT_DEVICE="/dev/mapper/"usb_mount_$(basename "$USB_MOUNT_DEVICE")""
else else

File diff suppressed because it is too large Load Diff

View File

@ -14,11 +14,11 @@ for dev in "$@"; do
die "$dev: Unable to read LUKS header" die "$dev: Unable to read LUKS header"
done done
DEBUG "Hashing luks headers into /tmp/luksDump.txt" DEBUG "Hashing LUKS headers into /tmp/luksDump.txt"
sha256sum /tmp/lukshdr-* >/tmp/luksDump.txt || die "Unable to hash luks headers" sha256sum /tmp/lukshdr-* >/tmp/luksDump.txt || die "Unable to hash LUKS headers"
DEBUG "Removing /tmp/lukshdr-*" DEBUG "Removing /tmp/lukshdr-*"
rm /tmp/lukshdr-* rm /tmp/lukshdr-*
DEBUG "Extending PCR 6 with /tmp/luksDump.txt" DEBUG "Extending TPM PCR 6 with hash of LUKS headers from /tmp/luksDump.txt"
tpmr extend -ix 6 -if /tmp/luksDump.txt || tpmr extend -ix 6 -if /tmp/luksDump.txt ||
die "Unable to extend PCR" die "Unable to extend PCR"

View File

@ -3,14 +3,23 @@
TRACE "Under /bin/reboot" TRACE "Under /bin/reboot"
if [ "$CONFIG_DEBUG_OUTPUT" = "y" ]; then
#Generalize user prompt to continue reboot or go to recovery shell
read -r -n 1 -s -p "Press any key to continue reboot or 'r' to go to recovery shell: " REPLY
echo
if [ "$REPLY" = "r" ] || [ "$REPLY" = "R" ]; then
recovery "Reboot call bypassed to go into recovery shell to debug"
fi
fi
# Shut down TPM # Shut down TPM
if [ "$CONFIG_TPM" = "y" ]; then if [ "$CONFIG_TPM" = "y" ]; then
tpmr shutdown tpmr shutdown
fi fi
# Run special EC-based poweroff for Nitropad-Nxx # Run special EC-based poweroff for Nitropad-Nxx
if [ "${CONFIG_BOARD%_*}" = nitropad-nv41 || "${CONFIG_BOARD%_*}" = nitropad-ns51 ]; then if [ "${CONFIG_BOARD%_*}" = nitropad-nv41 ] || [ "${CONFIG_BOARD%_*}" = nitropad-ns51 ]; then
/bin/nitropad-shutdown.sh /bin/nitropad-shutdown.sh
fi fi
# Sync all mounted filesystems # Sync all mounted filesystems

View File

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# Retrieve the sealed TOTP secret and initialize a USB Security dongle with it # Retrieve the sealed TOTP secret and initialize a USB Security Dongle with it
. /etc/functions . /etc/functions

View File

@ -25,10 +25,10 @@ dd \
of="$TOTP_SECRET" \ of="$TOTP_SECRET" \
count=1 \ count=1 \
bs=20 \ bs=20 \
2>/dev/null \ 2>/dev/null ||
|| die "Unable to generate 20 random bytes" die "Unable to generate 20 random bytes"
secret="`base32 < $TOTP_SECRET`" secret="$(base32 <$TOTP_SECRET)"
pcrf="/tmp/secret/pcrf.bin" pcrf="/tmp/secret/pcrf.bin"
DEBUG "Sealing TOTP with actual state of PCR0-3" DEBUG "Sealing TOTP with actual state of PCR0-3"
tpmr pcrread 0 "$pcrf" tpmr pcrread 0 "$pcrf"
@ -40,16 +40,18 @@ DEBUG "Sealing TOTP with boot state of PCR4 (Going to recovery shell extends PCR
# zero on bare coreboot+linuxboot on x86 (boot mode: init) # zero on bare coreboot+linuxboot on x86 (boot mode: init)
# already extended on ppc64 per BOOTKERNEL (skiboot) which boots heads. # already extended on ppc64 per BOOTKERNEL (skiboot) which boots heads.
# Read from event log to catch both cases, even when called from recovery shell. # Read from event log to catch both cases, even when called from recovery shell.
tpmr calcfuturepcr 4 >> "$pcrf" tpmr calcfuturepcr 4 >>"$pcrf"
# pcr 5 (kernel modules loaded) is not measured at sealing/unsealing of totp # pcr 5 (kernel modules loaded) is not measured at sealing/unsealing of totp
DEBUG "Sealing TOTP neglecting PCR5 involvement (Dynamically loaded kernel modules are not firmware integrity attestation related)" DEBUG "Sealing TOTP neglecting PCR5 involvement (Dynamically loaded kernel modules are not firmware integrity attestation related)"
# pcr 6 (drive luks header) is not measured at sealing/unsealing of totp # pcr 6 (drive LUKS header) is not measured at sealing/unsealing of totp
DEBUG "Sealing TOTP without PCR6 involvement (LUKS header consistency is not firmware integrity attestation related)" DEBUG "Sealing TOTP without PCR6 involvement (LUKS header consistency is not firmware integrity attestation related)"
# pcr 7 is containing measurements of user injected stuff in cbfs # pcr 7 is containing measurements of user injected stuff in cbfs
tpmr pcrread -a 7 "$pcrf" tpmr pcrread -a 7 "$pcrf"
tpmr seal "$TOTP_SECRET" "$TPM_NVRAM_SPACE" 0,1,2,3,4,7 "$pcrf" 312 "" "$TPM_PASSWORD" \ #Make sure we clear the TPM Owner Password from memory in case it failed to be used to seal TOTP
|| die "Unable to write sealed secret to NVRAM" tpmr seal "$TOTP_SECRET" "$TPM_NVRAM_SPACE" 0,1,2,3,4,7 "$pcrf" 312 "" "$TPM_PASSWORD" ||
shred -n 10 -z -u "$TOTP_SEALED" 2> /dev/null die "Unable to write sealed secret to NVRAM from seal-totp"
#Make sure we clear TPM TOTP sealed if we succeed to seal TOTP
shred -n 10 -z -u "$TOTP_SEALED" 2>/dev/null
url="otpauth://totp/$HOST?secret=$secret" url="otpauth://totp/$HOST?secret=$secret"
secret="" secret=""

View File

@ -7,4 +7,4 @@ echo '*****'
prompt_new_owner_password prompt_new_owner_password
tpmr reset "$key_password" tpmr reset "$tpm_owner_password"

View File

@ -5,9 +5,9 @@
SECRET_DIR="/tmp/secret" SECRET_DIR="/tmp/secret"
PRIMARY_HANDLE="0x81000000" PRIMARY_HANDLE="0x81000000"
ENC_SESSION_FILE="enc.ctx" ENC_SESSION_FILE="$SECRET_DIR/enc.ctx"
DEC_SESSION_FILE="dec.ctx" DEC_SESSION_FILE="$SECRET_DIR/dec.ctx"
PRIMARY_HANDLE_FILE="primary.handle" PRIMARY_HANDLE_FILE="$SECRET_DIR/primary.handle"
# PCR size in bytes. Set when we determine what TPM version is in use. # PCR size in bytes. Set when we determine what TPM version is in use.
# TPM1 PCRs are always 20 bytes. TPM2 is allowed to provide multiple PCR banks # TPM1 PCRs are always 20 bytes. TPM2 is allowed to provide multiple PCR banks
@ -115,7 +115,7 @@ extend_pcr_state() {
shift shift
if is_hash "$alg" "$next"; then if is_hash "$alg" "$next"; then
extend="$next" extend="$next"
else else
extend="$("${alg}sum" <"$next" | cut -d' ' -f1)" extend="$("${alg}sum" <"$next" | cut -d' ' -f1)"
fi fi
state="$(echo "$state$extend" | hex2bin | "${alg}sum" | cut -d' ' -f1)" state="$(echo "$state$extend" | hex2bin | "${alg}sum" | cut -d' ' -f1)"
@ -127,7 +127,7 @@ extend_pcr_state() {
# different arguments for grep. Those formats are shown below as heredocs to # different arguments for grep. Those formats are shown below as heredocs to
# keep all the data, including whitespaces: # keep all the data, including whitespaces:
# 1) TPM2 log, which can hold multiple hash algorithms at once: # 1) TPM2 log, which can hold multiple hash algorithms at once:
: << 'EOF' : <<'EOF'
TPM2 log: TPM2 log:
Specification: 2.00 Specification: 2.00
Platform class: PC Client Platform class: PC Client
@ -140,7 +140,7 @@ TPM2 log entry 1:
Event data: FMAP: FMAP Event data: FMAP: FMAP
EOF EOF
# 2) TPM1.2 log (aka TCPA), digest is always SHA1: # 2) TPM1.2 log (aka TCPA), digest is always SHA1:
: << 'EOF' : <<'EOF'
TCPA log: TCPA log:
Specification: 1.21 Specification: 1.21
Platform class: PC Client Platform class: PC Client
@ -152,7 +152,7 @@ TCPA log entry 1:
EOF EOF
# 3) coreboot-specific format: # 3) coreboot-specific format:
# 3.5) older versions printed 'coreboot TCPA log', even though it isn't TCPA # 3.5) older versions printed 'coreboot TCPA log', even though it isn't TCPA
: << 'EOF' : <<'EOF'
coreboot TPM log: coreboot TPM log:
PCR-2 27c4f1fa214480c8626397a15981ef3a9323717f SHA1 [FMAP: FMAP] PCR-2 27c4f1fa214480c8626397a15981ef3a9323717f SHA1 [FMAP: FMAP]
@ -194,25 +194,25 @@ $0 ~ pcr {
# is returned in binary form. # is returned in binary form.
replay_pcr() { replay_pcr() {
TRACE "Under /bin/tpmr:replay_pcr" TRACE "Under /bin/tpmr:replay_pcr"
if [ -z "$2" ] ; then if [ -z "$2" ]; then
>&2 echo "No PCR number passed" echo >&2 "No PCR number passed"
return return
fi fi
if [ "$2" -ge 8 ] ; then if [ "$2" -ge 8 ]; then
>&2 echo "Illegal PCR number ($2)" echo >&2 "Illegal PCR number ($2)"
return return
fi fi
local log=`cbmem -L` local log=$(cbmem -L)
local alg="$1" local alg="$1"
local pcr="$2" local pcr="$2"
local alg_digits=0 local alg_digits=0
# SHA-1 hashes are 40 chars # SHA-1 hashes are 40 chars
if [ "$alg" = "sha1" ] ; then alg_digits=40; fi if [ "$alg" = "sha1" ]; then alg_digits=40; fi
# SHA-256 hashes are 64 chars # SHA-256 hashes are 64 chars
if [ "$alg" = "sha256" ] ; then alg_digits=64; fi if [ "$alg" = "sha256" ]; then alg_digits=64; fi
shift 2 shift 2
replayed_pcr=$(extend_pcr_state $alg $(printf "%.${alg_digits}d" 0) \ replayed_pcr=$(extend_pcr_state $alg $(printf "%.${alg_digits}d" 0) \
$(echo "$log" | awk -v alg=$alg -v pcr=$pcr -f <(echo $AWK_PROG)) $@) $(echo "$log" | awk -v alg=$alg -v pcr=$pcr -f <(echo $AWK_PROG)) $@)
echo $replayed_pcr | hex2bin echo $replayed_pcr | hex2bin
DEBUG "Replayed cbmem -L clean boot state of PCR=$pcr ALG=$alg : $replayed_pcr" DEBUG "Replayed cbmem -L clean boot state of PCR=$pcr ALG=$alg : $replayed_pcr"
# To manually introspect current PCR values: # To manually introspect current PCR values:
@ -225,24 +225,28 @@ replay_pcr() {
# PCR-5, depending on which modules are loaded for given board: # PCR-5, depending on which modules are loaded for given board:
# tpmr calcfuturepcr 5 module0.ko module1.ko module2.ko | xxd -p # tpmr calcfuturepcr 5 module0.ko module1.ko module2.ko | xxd -p
# PCR-6 and PCR-7: similar to 5, but with different files passed # PCR-6 and PCR-7: similar to 5, but with different files passed
# (6: luks header, 7: user related cbfs files loaded from cbfs-init) # (6: LUKS header, 7: user related cbfs files loaded from cbfs-init)
} }
tpm2_extend() { tpm2_extend() {
TRACE "Under /bin/tpmr:tpm2_extend" TRACE "Under /bin/tpmr:tpm2_extend"
while true; do while true; do
case "$1" in case "$1" in
-ix) -ix)
index="$2" index="$2"
shift 2;; shift 2
-ic) ;;
hash="$(echo -n "$2"|sha256sum|cut -d' ' -f1)" -ic)
shift 2;; hash="$(echo -n "$2" | sha256sum | cut -d' ' -f1)"
-if) shift 2
hash="$(sha256sum "$2"|cut -d' ' -f1)" ;;
shift 2;; -if)
*) hash="$(sha256sum "$2" | cut -d' ' -f1)"
break;; shift 2
;;
*)
break
;;
esac esac
done done
tpm2 pcrextend "$index:sha256=$hash" tpm2 pcrextend "$index:sha256=$hash"
@ -253,57 +257,78 @@ tpm2_counter_read() {
TRACE "Under /bin/tpmr:tpm2_counter_read" TRACE "Under /bin/tpmr:tpm2_counter_read"
while true; do while true; do
case "$1" in case "$1" in
-ix) -ix)
index="$2" index="$2"
shift 2;; shift 2
*) ;;
break;; *)
break
;;
esac esac
done done
echo "$index: `tpm2 nvread 0x$index | xxd -pc8`" echo "$index: $(tpm2 nvread 0x$index | xxd -pc8)"
} }
tpm2_counter_inc() { tpm2_counter_inc() {
TRACE "Under /bin/tpmr:tpm2_counter_inc" TRACE "Under /bin/tpmr:tpm2_counter_inc"
while true; do while true; do
case "$1" in case "$1" in
-ix) -ix)
index="$2" index="$2"
shift 2;; shift 2
-pwdc) ;;
pwd="$2" -pwdc)
shift 2;; pwd="$2"
*) shift 2
break;; ;;
*)
break
;;
esac esac
done done
tpm2 nvincrement "0x$index" > /dev/console tpm2 nvincrement "0x$index" >/dev/console
echo "$index: `tpm2 nvread 0x$index | xxd -pc8`" echo "$index: $(tpm2 nvread 0x$index | xxd -pc8)"
} }
tpm2_counter_cre() { tpm1_counter_create() {
TRACE "Under /bin/tpmr:tpm2_counter_cre" TRACE "Under /bin/tpmr:tpm1_counter_create"
# tpmr handles the TPM owner password (from cache or prompt), but all
# other parameters for TPM1 are passed directly, and TPM2 mimics the
# TPM1 interface.
prompt_tpm_owner_password
if ! tpm counter_create -pwdo "$(cat "/tmp/secret/tpm_owner_password")" "$@"; then
DEBUG "Failed to create counter from tpm1_counter_create. Wiping /tmp/secret/tpm_owner_password"
shred -n 10 -z -u /tmp/secret/tpm_owner_password
die "Unable to create counter from tpm1_counter_create"
fi
}
tpm2_counter_create() {
TRACE "Under /bin/tpmr:tpm2_counter_create"
while true; do while true; do
case "$1" in case "$1" in
-pwdo) -pwdc)
pwdo="$2" pwd="$2"
shift 2;; shift 2
-pwdof) ;;
pwdo="file:$2" -la)
shift 2;; label="$2"
-pwdc) shift 2
pwd="$2" ;;
shift 2;; *)
-la) break
label="$2" ;;
shift 2;;
*)
break;;
esac esac
done done
rand_index="1`dd if=/dev/urandom bs=1 count=3 | xxd -pc3`" prompt_tpm_owner_password
rand_index="1$(dd if=/dev/urandom bs=1 count=3 | xxd -pc3)"
tpm2 nvdefine -C o -s 8 -a "ownerread|authread|authwrite|nt=1" \ tpm2 nvdefine -C o -s 8 -a "ownerread|authread|authwrite|nt=1" \
-P "$(tpm2_password_hex "$pwdo")" "0x$rand_index" > /dev/console -P "$(tpm2_password_hex "$(cat "/tmp/secret/tpm_owner_password")")" "0x$rand_index" >/dev/console ||
{
DEBUG "Failed to create counter from tpm2_counter_create. Wiping /tmp/secret/tpm_owner_password"
shred -n 10 -z -u /tmp/secret/tpm_owner_password
die "Unable to create counter from tpm2_counter_create"
}
echo "$rand_index: (valid after an increment)" echo "$rand_index: (valid after an increment)"
} }
@ -311,20 +336,20 @@ tpm2_startsession() {
TRACE "Under /bin/tpmr:tpm2_startsession" TRACE "Under /bin/tpmr:tpm2_startsession"
mkdir -p "$SECRET_DIR" mkdir -p "$SECRET_DIR"
tpm2 flushcontext -Q \ tpm2 flushcontext -Q \
--transient-object \ --transient-object ||
|| die "tpm2_flushcontext: unable to flush transient handles" die "tpm2_flushcontext: unable to flush transient handles"
tpm2 flushcontext -Q \ tpm2 flushcontext -Q \
--loaded-session \ --loaded-session ||
|| die "tpm2_flushcontext: unable to flush sessions" die "tpm2_flushcontext: unable to flush sessions"
tpm2 flushcontext -Q \ tpm2 flushcontext -Q \
--saved-session \ --saved-session ||
|| die "tpm2_flushcontext: unable to flush saved session" die "tpm2_flushcontext: unable to flush saved session"
tpm2 readpublic -Q -c "$PRIMARY_HANDLE" -t "/tmp/$PRIMARY_HANDLE_FILE" tpm2 readpublic -Q -c "$PRIMARY_HANDLE" -t "$PRIMARY_HANDLE_FILE"
tpm2 startauthsession -Q -c "/tmp/$PRIMARY_HANDLE_FILE" --hmac-session -S "/tmp/$ENC_SESSION_FILE" tpm2 startauthsession -Q -c "$PRIMARY_HANDLE_FILE" --hmac-session -S "$ENC_SESSION_FILE"
tpm2 startauthsession -Q -c "/tmp/$PRIMARY_HANDLE_FILE" --hmac-session -S "/tmp/$DEC_SESSION_FILE" tpm2 startauthsession -Q -c "$PRIMARY_HANDLE_FILE" --hmac-session -S "$DEC_SESSION_FILE"
tpm2 sessionconfig -Q --disable-encrypt "/tmp/$DEC_SESSION_FILE" tpm2 sessionconfig -Q --disable-encrypt "$DEC_SESSION_FILE"
} }
# Use cleanup_session() with at_exit to release a TPM2 session and delete the # Use cleanup_session() with at_exit to release a TPM2 session and delete the
@ -354,27 +379,27 @@ cleanup_shred() {
# tpm2_destroy: Destroy a sealed file in the TPM. The mechanism differs by # 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. # TPM version - TPM2 evicts the file object, so it no longer exists.
tpm2_destroy() { tpm2_destroy() {
index="$1" # Index of the sealed file index="$1" # Index of the sealed file
size="$2" # Size of zeroes to overwrite for TPM1 (unused in TPM2) size="$2" # Size of zeroes to overwrite for TPM1 (unused in TPM2)
# Pad with up to 6 zeros, i.e. '0x81000001', '0x81001234', etc. # Pad with up to 6 zeros, i.e. '0x81000001', '0x81001234', etc.
handle="$(printf "0x81%6s" "$index" | tr ' ' 0)" handle="$(printf "0x81%6s" "$index" | tr ' ' 0)"
# remove possible data occupying this handle # remove possible data occupying this handle
tpm2 evictcontrol -Q -C p -c "$handle" 2>/dev/null \ tpm2 evictcontrol -Q -C p -c "$handle" 2>/dev/null ||
|| die "Unable to evict secret" die "Unable to evict secret from TPM NVRAM"
} }
# tpm1_destroy: Destroy a sealed file in the TPM. The mechanism differs by # 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 # TPM version - TPM1 overwrites the file with zeroes, since this can be done
# without authorization. (Deletion requires authorization.) # without authorization. (Deletion requires authorization.)
tpm1_destroy() { tpm1_destroy() {
index="$1" # Index of the sealed file index="$1" # Index of the sealed file
size="$2" # Size of zeroes to overwrite for TPM1 size="$2" # Size of zeroes to overwrite for TPM1
dd if=/dev/zero bs="$size" count=1 of=/tmp/wipe-totp-zero dd if=/dev/zero bs="$size" count=1 of=/tmp/wipe-totp-zero
tpm nv_writevalue -in "$index" -if /tmp/wipe-totp-zero \ tpm nv_writevalue -in "$index" -if /tmp/wipe-totp-zero ||
|| die "Unable to wipe sealed secret" die "Unable to wipe sealed secret from TPM NVRAM"
} }
# tpm2_seal: Seal a file against PCR values and, optionally, a password. # tpm2_seal: Seal a file against PCR values and, optionally, a password.
@ -388,13 +413,13 @@ tpm2_seal() {
index="$2" index="$2"
pcrl="$3" #0,1,2,3,4,5,6,7 (does not include algorithm prefix) pcrl="$3" #0,1,2,3,4,5,6,7 (does not include algorithm prefix)
pcrf="$4" pcrf="$4"
sealed_size="$5" # Not used for TPM2 sealed_size="$5" # Not used for TPM2
pass="$6" # May be empty to seal with no password pass="$6" # May be empty to seal with no password
tpm_password="$7" # Owner password - will prompt if needed and not empty tpm_password="$7" # Owner password - will prompt if needed and not empty
# Owner password is always needed for TPM2. # TPM Owner Password is always needed for TPM2.
mkdir -p "$SECRET_DIR" mkdir -p "$SECRET_DIR"
bname="`basename $file`" bname="$(basename $file)"
# Pad with up to 6 zeros, i.e. '0x81000001', '0x81001234', etc. # Pad with up to 6 zeros, i.e. '0x81000001', '0x81001234', etc.
handle="$(printf "0x81%6s" "$index" | tr ' ' 0)" handle="$(printf "0x81%6s" "$index" | tr ' ' 0)"
@ -403,8 +428,8 @@ tpm2_seal() {
# Create a policy requiring both PCRs and the object's authentication # Create a policy requiring both PCRs and the object's authentication
# value using a trial session. # value using a trial session.
TRIAL_SESSION=/tmp/sealfile_trial.session TRIAL_SESSION="$SECRET_DIR/sealfile_trial.session"
AUTH_POLICY=/tmp/sealfile_auth.policy AUTH_POLICY="$SECRET_DIR/sealfile_auth.policy"
rm -f "$TRIAL_SESSION" "$AUTH_POLICY" rm -f "$TRIAL_SESSION" "$AUTH_POLICY"
tpm2 startauthsession -g sha256 -S "$TRIAL_SESSION" tpm2 startauthsession -g sha256 -S "$TRIAL_SESSION"
# We have to clean up the session # We have to clean up the session
@ -430,25 +455,30 @@ tpm2_seal() {
# (The default is to allow either policy auth _or_ password auth. In # (The default is to allow either policy auth _or_ password auth. In
# this case the policy includes the password, and we don't want to allow # this case the policy includes the password, and we don't want to allow
# the password on its own.) # the password on its own.)
tpm2 create -Q -C "/tmp/$PRIMARY_HANDLE_FILE" \ tpm2 create -Q -C "$PRIMARY_HANDLE_FILE" \
-i "$file" \ -i "$file" \
-u "$SECRET_DIR/$bname.priv" \ -u "$SECRET_DIR/$bname.priv" \
-r "$SECRET_DIR/$bname.pub" \ -r "$SECRET_DIR/$bname.pub" \
-L "$AUTH_POLICY" \ -L "$AUTH_POLICY" \
-S "/tmp/$DEC_SESSION_FILE" \ -S "$DEC_SESSION_FILE" \
-a "fixedtpm|fixedparent|adminwithpolicy" \ -a "fixedtpm|fixedparent|adminwithpolicy" \
"${CREATE_PASS_ARGS[@]}" "${CREATE_PASS_ARGS[@]}"
tpm2 load -Q -C "/tmp/$PRIMARY_HANDLE_FILE" \ tpm2 load -Q -C "$PRIMARY_HANDLE_FILE" \
-u "$SECRET_DIR/$bname.priv" -r "$SECRET_DIR/$bname.pub" \ -u "$SECRET_DIR/$bname.priv" -r "$SECRET_DIR/$bname.pub" \
-c "$SECRET_DIR/$bname.seal.ctx" -c "$SECRET_DIR/$bname.seal.ctx"
prompt_tpm_password prompt_tpm_owner_password
# remove possible data occupying this handle # remove possible data occupying this handle
tpm2 evictcontrol -Q -C o -P "$(tpm2_password_hex "$tpm_password")" \ tpm2 evictcontrol -Q -C o -P "$(tpm2_password_hex "$tpm_owner_password")" \
-c "$handle" 2>/dev/null || true -c "$handle" 2>/dev/null || true
DO_WITH_DEBUG --mask-position 6 \ DO_WITH_DEBUG --mask-position 6 \
tpm2 evictcontrol -Q -C o -P "$(tpm2_password_hex "$tpm_password")" \ tpm2 evictcontrol -Q -C o -P "$(tpm2_password_hex "$tpm_owner_password")" \
-c "$SECRET_DIR/$bname.seal.ctx" "$handle" -c "$SECRET_DIR/$bname.seal.ctx" "$handle" ||
{
DEBUG "Failed to write sealed secret to NVRAM from tpm2_seal. Wiping /tmp/secret/tpm_owner_password"
shred -n 10 -z -u /tmp/secret/tpm_owner_password
die "Unable to write sealed secret to TPM NVRAM"
}
} }
tpm1_seal() { tpm1_seal() {
TRACE "Under /bin/tpmr:tpm1_seal" TRACE "Under /bin/tpmr:tpm1_seal"
@ -457,8 +487,8 @@ tpm1_seal() {
pcrl="$3" #0,1,2,3,4,5,6,7 (does not include algorithm prefix) pcrl="$3" #0,1,2,3,4,5,6,7 (does not include algorithm prefix)
pcrf="$4" pcrf="$4"
sealed_size="$5" sealed_size="$5"
pass="$6" # May be empty to seal with no password pass="$6" # May be empty to seal with no password
tpm_password="$7" # Owner password - will prompt if needed and not empty tpm_password="$7" # Owner password - will prompt if needed and not empty
sealed_file="$SECRET_DIR/tpm1_seal_sealed.bin" sealed_file="$SECRET_DIR/tpm1_seal_sealed.bin"
at_exit cleanup_shred "$sealed_file" at_exit cleanup_shred "$sealed_file"
@ -477,8 +507,8 @@ tpm1_seal() {
# Read each PCR_SIZE block from the file and pass as hex # Read each PCR_SIZE block from the file and pass as hex
POLICY_ARGS+=(-ix "$pcr" POLICY_ARGS+=(-ix "$pcr"
"$(dd if="$pcrf" skip="$pcr_file_index" bs="$PCR_SIZE" count=1 status=none | xxd -p | tr -d ' ')" "$(dd if="$pcrf" skip="$pcr_file_index" bs="$PCR_SIZE" count=1 status=none | xxd -p | tr -d ' ')"
) )
pcr_file_index=$((pcr_file_index+1)) pcr_file_index=$((pcr_file_index + 1))
done done
tpm sealfile2 \ tpm sealfile2 \
@ -487,25 +517,28 @@ tpm1_seal() {
-hk 40000000 \ -hk 40000000 \
"${POLICY_ARGS[@]}" "${POLICY_ARGS[@]}"
# try it without the owner password first # try it without the TPM Owner Password first
if ! tpm nv_writevalue -in "$index" -if "$sealed_file"; then if ! tpm nv_writevalue -in "$index" -if "$sealed_file"; then
# to create an nvram space we need the TPM owner password # to create an nvram space we need the TPM Owner Password
# and the TPM physical presence must be asserted. # and the TPM physical presence must be asserted.
# #
# The permissions are 0 since there is nothing special # The permissions are 0 since there is nothing special
# about the sealed file # about the sealed file
tpm physicalpresence -s \ tpm physicalpresence -s ||
|| warn "Unable to assert physical presence" warn "Unable to assert physical presence"
prompt_tpm_password prompt_tpm_owner_password
tpm nv_definespace -in "$index" -sz "$sealed_size" \ tpm nv_definespace -in "$index" -sz "$sealed_size" \
-pwdo "$tpm_password" -per 0 \ -pwdo "$tpm_password" -per 0 ||
|| warn "Unable to define NVRAM space; trying anyway" warn "Unable to define TPM NVRAM space; trying anyway"
tpm nv_writevalue -in "$index" -if "$sealed_file" ||
tpm nv_writevalue -in "$index" -if "$sealed_file" \ {
|| die "Unable to write sealed secret to NVRAM" DEBUG "Failed to write sealed secret to NVRAM from tpm1_seal. Wiping /tmp/secret/tpm_owner_password"
shred -n 10 -z -u /tmp/secret/tpm_owner_password
die "Unable to write sealed secret to TPM NVRAM"
}
fi fi
} }
@ -531,12 +564,13 @@ tpm2_unseal() {
# If we don't have the primary handle (TPM hasn't been reset), tpm2 will # If we don't have the primary handle (TPM hasn't been reset), tpm2 will
# print nonsense error messages about an unexpected handle value. We # print nonsense error messages about an unexpected handle value. We
# can't do anything without a primary handle. # can't do anything without a primary handle.
if [ ! -f "/tmp/$PRIMARY_HANDLE_FILE" ]; then if [ ! -f "$PRIMARY_HANDLE_FILE" ]; then
DEBUG "tpm2_unseal: No primary handle, cannot attempt to unseal" DEBUG "tpm2_unseal: No primary handle, cannot attempt to unseal"
warn "No TPM primary handle. You must reset TPM to seal secret to TPM NVRAM"
exit 1 exit 1
fi fi
POLICY_SESSION=/tmp/unsealfile_policy.session POLICY_SESSION="$SECRET_DIR/unsealfile_policy.session"
rm -f "$POLICY_SESSION" rm -f "$POLICY_SESSION"
tpm2 startauthsession -Q -g sha256 -S "$POLICY_SESSION" --policy-session tpm2 startauthsession -Q -g sha256 -S "$POLICY_SESSION" --policy-session
at_exit cleanup_session "$POLICY_SESSION" at_exit cleanup_session "$POLICY_SESSION"
@ -554,7 +588,7 @@ tpm2_unseal() {
fi fi
tpm2 unseal -Q -c "$handle" -p "session:$POLICY_SESSION$UNSEAL_PASS_SUFFIX" \ tpm2 unseal -Q -c "$handle" -p "session:$POLICY_SESSION$UNSEAL_PASS_SUFFIX" \
-S "/tmp/$ENC_SESSION_FILE" > "$file" -S "$ENC_SESSION_FILE" >"$file"
} }
tpm1_unseal() { tpm1_unseal() {
TRACE "Under /bin/tpmr:tpm1_unseal" TRACE "Under /bin/tpmr:tpm1_unseal"
@ -576,8 +610,8 @@ tpm1_unseal() {
tpm nv_readvalue \ tpm nv_readvalue \
-in "$index" \ -in "$index" \
-sz "$sealed_size" \ -sz "$sealed_size" \
-of "$sealed_file" \ -of "$sealed_file" ||
|| die "Unable to read sealed file from TPM NVRAM" die "Unable to read sealed file from TPM NVRAM"
PASS_ARGS=() PASS_ARGS=()
if [ "$pass" ]; then if [ "$pass" ]; then
@ -593,15 +627,18 @@ tpm1_unseal() {
tpm2_reset() { tpm2_reset() {
TRACE "Under /bin/tpmr:tpm2_reset" TRACE "Under /bin/tpmr:tpm2_reset"
key_password="$1" tpm_owner_password="$1"
mkdir -p "$SECRET_DIR" mkdir -p "$SECRET_DIR"
# output TPM Owner Password to a file to be reused in this boot session until recovery shell/reboot
DEBUG "Caching TPM Owner Password to $SECRET_DIR/tpm_owner_password"
echo -n "$tpm_owner_password" >"$SECRET_DIR/tpm_owner_password"
tpm2 clear -c platform || warn "Unable to clear TPM on platform hierarchy" tpm2 clear -c platform || warn "Unable to clear TPM on platform hierarchy"
tpm2 changeauth -c owner "$(tpm2_password_hex "$key_password")" tpm2 changeauth -c owner "$(tpm2_password_hex "$tpm_owner_password")"
tpm2 changeauth -c endorsement "$(tpm2_password_hex "$key_password")" tpm2 changeauth -c endorsement "$(tpm2_password_hex "$tpm_owner_password")"
tpm2 createprimary -C owner -g sha256 -G "${CONFIG_PRIMARY_KEY_TYPE:-rsa}" \ tpm2 createprimary -C owner -g sha256 -G "${CONFIG_PRIMARY_KEY_TYPE:-rsa}" \
-c "$SECRET_DIR/primary.ctx" -P "$(tpm2_password_hex "$key_password")" -c "$SECRET_DIR/primary.ctx" -P "$(tpm2_password_hex "$tpm_owner_password")"
tpm2 evictcontrol -C owner -c "$SECRET_DIR/primary.ctx" "$PRIMARY_HANDLE" \ tpm2 evictcontrol -C owner -c "$SECRET_DIR/primary.ctx" "$PRIMARY_HANDLE" \
-P "$(tpm2_password_hex "$key_password")" -P "$(tpm2_password_hex "$tpm_owner_password")"
shred -u "$SECRET_DIR/primary.ctx" shred -u "$SECRET_DIR/primary.ctx"
tpm2_startsession tpm2_startsession
@ -610,7 +647,7 @@ tpm2_reset() {
# * --max-tries=10: Allow 10 failures before lockout. This allows the # * --max-tries=10: Allow 10 failures before lockout. This allows the
# user to quickly "burst" 10 failures without significantly impacting # user to quickly "burst" 10 failures without significantly impacting
# the rate allowed for a dictionary attacker. # the rate allowed for a dictionary attacker.
# Most TPM2 flows ask for the owner password 2-4 times, so this allows # Most TPM2 flows ask for the TPM Owner Password 2-4 times, so this allows
# a handful of mistypes and some headroom for an expected unseal # a handful of mistypes and some headroom for an expected unseal
# failure if firmware is updated. # failure if firmware is updated.
# Remember that an auth failure is also counted any time an unclean # Remember that an auth failure is also counted any time an unclean
@ -626,7 +663,7 @@ tpm2_reset() {
--max-tries=10 \ --max-tries=10 \
--recovery-time=3600 \ --recovery-time=3600 \
--lockout-recovery-time=0 \ --lockout-recovery-time=0 \
--auth="session:/tmp/$ENC_SESSION_FILE" --auth="session:$ENC_SESSION_FILE"
# Set a random DA lockout password, so the DA lockout can't be cleared # Set a random DA lockout password, so the DA lockout can't be cleared
# with a password. Heads doesn't offer dictionary attach reset, instead # with a password. Heads doesn't offer dictionary attach reset, instead
@ -639,15 +676,18 @@ tpm2_reset() {
} }
tpm1_reset() { tpm1_reset() {
TRACE "Under /bin/tpmr:tpm1_reset" TRACE "Under /bin/tpmr:tpm1_reset"
key_password="$1" tpm_owner_password="$1"
mkdir -p "$SECRET_DIR"
# output tpm_owner_password to a file to be reused in this boot session until recovery shell/reboot
DEBUG "Caching TPM Owner Password to $SECRET_DIR/tpm_owner_password"
echo -n "$tpm_owner_password" >"$SECRET_DIR/tpm_owner_password"
# Make sure the TPM is ready to be reset # Make sure the TPM is ready to be reset
tpm physicalpresence -s tpm physicalpresence -s
tpm physicalenable tpm physicalenable
tpm physicalsetdeactivated -c tpm physicalsetdeactivated -c
tpm forceclear tpm forceclear
tpm physicalenable tpm physicalenable
tpm takeown -pwdo "$key_password" tpm takeown -pwdo "$tpm_owner_password"
# And now turn it all back on # And now turn it all back on
tpm physicalpresence -s tpm physicalpresence -s
@ -660,20 +700,20 @@ tpm2_kexec_finalize() {
TRACE "Under /bin/tpmr:tpm2_kexec_finalize" TRACE "Under /bin/tpmr:tpm2_kexec_finalize"
# Flush sessions and transient objects # Flush sessions and transient objects
tpm2 flushcontext -Q --transient-object \ tpm2 flushcontext -Q --transient-object ||
|| warn "tpm2_flushcontext: unable to flush transient handles" warn "tpm2_flushcontext: unable to flush transient handles"
tpm2 flushcontext -Q --loaded-session \ tpm2 flushcontext -Q --loaded-session ||
|| warn "tpm2_flushcontext: unable to flush sessions" warn "tpm2_flushcontext: unable to flush sessions"
tpm2 flushcontext -Q --saved-session \ tpm2 flushcontext -Q --saved-session ||
|| warn "tpm2_flushcontext: unable to flush saved session" warn "tpm2_flushcontext: unable to flush saved session"
# Add a random passphrase to platform hierarchy to prevent TPM2 from # Add a random passphrase to platform hierarchy to prevent TPM2 from
# being cleared in the OS. # being cleared in the OS.
# This passphrase is only effective before the next boot. # This passphrase is only effective before the next boot.
echo "Locking TPM2 platform hierarchy..." echo "Locking TPM2 platform hierarchy..."
randpass=$(dd if=/dev/urandom bs=4 count=1 status=none | xxd -p) randpass=$(dd if=/dev/urandom bs=4 count=1 status=none | xxd -p)
tpm2 changeauth -c platform "$randpass" \ tpm2 changeauth -c platform "$randpass" ||
|| warn "Failed to lock platform hierarchy of TPM2" warn "Failed to lock platform hierarchy of TPM2"
} }
tpm2_shutdown() { tpm2_shutdown() {
@ -693,72 +733,101 @@ fi
# TPM1 - most commands forward directly to tpm, but some are still wrapped for # TPM1 - most commands forward directly to tpm, but some are still wrapped for
# consistency with tpm2. # consistency with tpm2.
if [ "$CONFIG_TPM2_TOOLS" != "y" ]; then if [ "$CONFIG_TPM2_TOOLS" != "y" ]; then
PCR_SIZE=20 # TPM1 PCRs are always SHA-1 PCR_SIZE=20 # TPM1 PCRs are always SHA-1
subcmd="$1" subcmd="$1"
# Don't shift yet, for most commands we will just forward to tpm. # Don't shift yet, for most commands we will just forward to tpm.
case "$subcmd" in case "$subcmd" in
pcrread) pcrread)
shift; tpm1_pcrread "$@";; shift
pcrsize) tpm1_pcrread "$@"
echo "$PCR_SIZE";; ;;
calcfuturepcr) pcrsize)
shift; replay_pcr "sha1" "$@";; echo "$PCR_SIZE"
destroy) ;;
shift; tpm1_destroy "$@";; calcfuturepcr)
seal) shift
shift; tpm1_seal "$@";; replay_pcr "sha1" "$@"
startsession) ;;
;; # Nothing on TPM1. counter_create)
unseal) shift
shift; tpm1_unseal "$@";; tpm1_counter_create "$@"
reset) ;;
shift; tpm1_reset "$@";; destroy)
kexec_finalize) shift
;; # Nothing on TPM1. tpm1_destroy "$@"
shutdown) ;;
;; # Nothing on TPM1. seal)
*) shift
DEBUG "Direct translation from tpmr to tpm1 call" tpm1_seal "$@"
DO_WITH_DEBUG exec tpm "$@" ;;
;; startsession) ;; # Nothing on TPM1.
unseal)
shift
tpm1_unseal "$@"
;;
reset)
shift
tpm1_reset "$@"
;;
kexec_finalize) ;; # Nothing on TPM1.
shutdown) ;; # Nothing on TPM1.
*)
DEBUG "Direct translation from tpmr to tpm1 call"
DO_WITH_DEBUG exec tpm "$@"
;;
esac esac
exit 0 exit 0
fi fi
# TPM2 - all commands implemented as wrappers around tpm2 # TPM2 - all commands implemented as wrappers around tpm2
PCR_SIZE=32 # We use the SHA-256 PCRs PCR_SIZE=32 # We use the SHA-256 PCRs
subcmd="$1" subcmd="$1"
shift 1 shift 1
case "$subcmd" in case "$subcmd" in
pcrread) pcrread)
tpm2_pcrread "$@";; tpm2_pcrread "$@"
pcrsize) ;;
echo "$PCR_SIZE";; pcrsize)
calcfuturepcr) echo "$PCR_SIZE"
replay_pcr "sha256" "$@";; ;;
extend) calcfuturepcr)
tpm2_extend "$@";; replay_pcr "sha256" "$@"
counter_read) ;;
tpm2_counter_read "$@";; extend)
counter_increment) tpm2_extend "$@"
tpm2_counter_inc "$@";; ;;
counter_create) counter_read)
tpm2_counter_cre "$@";; tpm2_counter_read "$@"
destroy) ;;
tpm2_destroy "$@";; counter_increment)
seal) tpm2_counter_inc "$@"
tpm2_seal "$@";; ;;
startsession) counter_create)
tpm2_startsession "$@";; tpm2_counter_create "$@"
unseal) ;;
tpm2_unseal "$@";; destroy)
reset) tpm2_destroy "$@"
tpm2_reset "$@";; ;;
kexec_finalize) seal)
tpm2_kexec_finalize "$@";; tpm2_seal "$@"
shutdown) ;;
tpm2_shutdown "$@";; startsession)
*) tpm2_startsession "$@"
echo "Command $subcmd not wrapped!" ;;
exit 1 unseal)
tpm2_unseal "$@"
;;
reset)
tpm2_reset "$@"
;;
kexec_finalize)
tpm2_kexec_finalize "$@"
;;
shutdown)
tpm2_shutdown "$@"
;;
*)
echo "Command $subcmd not wrapped!"
exit 1
;;
esac esac

View File

@ -8,14 +8,14 @@ TOTP_SECRET="/tmp/secret/totp.key"
TRACE "Under /bin/unseal-totp" TRACE "Under /bin/unseal-totp"
if [ "$CONFIG_TPM" = "y" ]; then if [ "$CONFIG_TPM" = "y" ]; then
tpmr unseal 4d47 0,1,2,3,4,7 312 "$TOTP_SECRET" \ tpmr unseal 4d47 0,1,2,3,4,7 312 "$TOTP_SECRET" ||
|| die "Unable to unseal totp secret" die "Unable to unseal TOTP secret"
fi fi
if ! totp -q < "$TOTP_SECRET"; then if ! totp -q <"$TOTP_SECRET"; then
shred -n 10 -z -u "$TOTP_SECRET" 2> /dev/null shred -n 10 -z -u "$TOTP_SECRET" 2>/dev/null
die 'Unable to compute TOTP hash?' die 'Unable to compute TOTP hash?'
fi fi
shred -n 10 -z -u "$TOTP_SECRET" 2> /dev/null shred -n 10 -z -u "$TOTP_SECRET" 2>/dev/null
exit 0 exit 0

View File

@ -53,6 +53,163 @@ preserve_rom() {
done done
} }
confirm_gpg_card() {
TRACE "Under /etc/ash_functions:confirm_gpg_card"
#Skip prompts if we are currently using a known GPG key material Thumb drive backup and keys are unlocked pinentry
#TODO: probably export CONFIG_GPG_KEY_BACKUP_IN_USE but not under /etc/user.config?
#Toggle to come in next PR, but currently we don't have a way to toggle it back to n if config.user flashed back in rom
if [[ "$CONFIG_HAVE_GPG_KEY_BACKUP" == "y" && "$CONFIG_GPG_KEY_BACKUP_IN_USE" == "y" ]]; then
DEBUG "Using known GPG key material Thumb drive backup and keys are unlocked and useable through pinentry"
return
fi
if [ "$CONFIG_HAVE_GPG_KEY_BACKUP" == "y" ]; then
message="Please confirm that your GPG card is inserted(Y/n) or your GPG key material (b)backup thumbdrive is inserted [Y/n/b]: "
else
# Generic message if no known key material backup
message="Please confirm that your GPG card is inserted [Y/n]: "
fi
read \
-n 1 \
-p "$message" \
card_confirm
echo
if [ "$card_confirm" != "y" \
-a "$card_confirm" != "Y" \
-a "$card_confirm" != "b" \
-a -n "$card_confirm" ] \
; then
die "gpg card not confirmed"
fi
# If user has known GPG key material Thumb drive backup and asked to use it
if [[ "$CONFIG_HAVE_GPG_KEY_BACKUP" == "y" && "$card_confirm" == "b" ]]; then
#Only mount and import GPG key material thumb drive backup once
if [ ! "$CONFIG_GPG_KEY_BACKUP_IN_USE" == "y" ]; then
CR_NONCE="/tmp/secret/cr_nonce"
CR_SIG="$CR_NONCE.sig"
#Wipe any previous CR_NONCE and CR_SIG
shred -n 10 -z -u "$CR_NONCE" "$CR_SIG" >/dev/null 2>&1 || true
#Prompt user for configured GPG Admin PIN that will be passed along to mount-usb and to import gpg subkeys
echo
gpg_admin_pin=""
while [ -z "$gpg_admin_pin" ]; do
#TODO: change all passphrase prompts in codebase to include -r to prevent backslash escapes
read -r -s -p "Please enter GPG Admin PIN needed to use the GPG backup thumb drive: " gpg_admin_pin
echo
done
#prompt user to select the proper encrypted partition, which should the first one on next prompt
warn "Please select encrypted LUKS on GPG key material backup thumb drive (not public labeled one)"
mount-usb --pass "$gpg_admin_pin" || die "Unable to mount USB with provided GPG Admin PIN"
echo "++++ Testing detach-sign operation and verifiying against fused public key in ROM"
gpg --pinentry-mode=loopback --passphrase-file <(echo -n "${gpg_admin_pin}") --import /media/subkeys.sec >/dev/null 2>&1 ||
die "Unable to import GPG private subkeys"
#Do a detach signature to ensure gpg material is usable and cache passphrase to sign /boot from caller functions
dd if=/dev/urandom of="$CR_NONCE" bs=20 count=1 >/dev/null 2>&1 ||
die "Unable to create $CR_NONCE to be detach-signed with GPG private signing subkey"
gpg --pinentry-mode=loopback --passphrase-file <(echo -n "${gpg_admin_pin}") --detach-sign "$CR_NONCE" >/dev/null 2>&1 ||
die "Unable to detach-sign $CR_NONCE with GPG private signing subkey using GPG Admin PIN"
#verify detached signature against public key in rom
gpg --verify "$CR_SIG" "$CR_NONCE" > /dev/null 2>&1 && \
echo "++++ Local GPG keyring can be used to sign/encrypt/authenticate in this boot session ++++" || \
die "Unable to verify $CR_SIG detached signature against public key in ROM"
#Wipe any previous CR_NONCE and CR_SIG
shred -n 10 -z -u "$CR_NONCE" "$CR_SIG" >/dev/null 2>&1 || true
#TODO: maybe just an export instead of setting /etc/user.config otherwise could be flashed in weird corner case situation
set_user_config "CONFIG_GPG_KEY_BACKUP_IN_USE" "y"
umount /media || die "Unable to unmount USB"
return
fi
fi
# setup the USB so we can reach the USB Security Dongle's smartcard
enable_usb
echo -e "\nVerifying presence of GPG card...\n"
# ensure we don't exit without retrying
errexit=$(set -o | grep errexit | awk '{print $2}')
set +e
gpg --card-status >/dev/null
if [ $? -ne 0 ]; then
# prompt for reinsertion and try a second time
read -n1 -r -p \
"Can't access GPG key; remove and reinsert, then press Enter to retry. " \
ignored
# restore prev errexit state
if [ "$errexit" = "on" ]; then
set -e
fi
# retry card status
gpg --card-status >/dev/null ||
die "gpg card read failed"
fi
# restore prev errexit state
if [ "$errexit" = "on" ]; then
set -e
fi
}
gpg_auth() {
if [[ "$CONFIG_HAVE_GPG_KEY_BACKUP" == "y" ]]; then
TRACE "Under /etc/ash_functions:gpg_auth"
# If we have a GPG key backup, we can use it to authenticate even if the card is lost
echo >&2 "!!!!! Please authenticate with OpenPGP smartcard/backup media to prove you are the owner of this machine !!!!!"
# Wipe any existing nonce and signature
shred -n 10 -z -u "$CR_NONCE" "$CR_SIG" 2>/dev/null || true
# In case of gpg_auth, we require confirmation of the card, so loop with confirm_gpg_card until we get it
false
while [ $? -ne 0 ]; do
# Call confirm_gpg_card in subshell to ensure GPG key material presence
( confirm_gpg_card )
done
# Perform a signing-based challenge-response,
# to authencate that the card plugged in holding
# the key to sign the list of boot files.
CR_NONCE="/tmp/secret/cr_nonce"
CR_SIG="$CR_NONCE.sig"
# Generate a random nonce
dd \
if=/dev/urandom \
of="$CR_NONCE" \
count=1 \
bs=20 \
2>/dev/null \
|| die "Unable to generate 20 random bytes"
# Sign the nonce
for tries in 1 2 3; do
if gpg --digest-algo SHA256 \
--detach-sign \
-o "$CR_SIG" \
"$CR_NONCE" > /dev/null 2>&1 \
&& gpg --verify "$CR_SIG" "$CR_NONCE" > /dev/null 2>&1 \
; then
shred -n 10 -z -u "$CR_NONCE" "$CR_SIG" 2>/dev/null || true
DEBUG "Under /etc/ash_functions:gpg_auth: success"
return 0
else
shred -n 10 -z -u "$CR_SIG" 2>/dev/null || true
if [ "$tries" -lt 3 ]; then
echo >&2 "!!!!! GPG authentication failed, please try again !!!!!"
continue
else
die "GPG authentication failed, please reboot and try again"
fi
fi
done
return 1
fi
}
recovery() { recovery() {
TRACE "Under /etc/ash_functions:recovery" TRACE "Under /etc/ash_functions:recovery"
echo >&2 "!!!!! $*" echo >&2 "!!!!! $*"
@ -70,6 +227,7 @@ recovery() {
. /tmp/config . /tmp/config
if [ "$CONFIG_TPM" = "y" ]; then if [ "$CONFIG_TPM" = "y" ]; then
DEBUG "Extending TPM PCR 4 for recovery shell access"
tpmr extend -ix 4 -ic recovery tpmr extend -ix 4 -ic recovery
fi fi
@ -80,6 +238,9 @@ recovery() {
fi fi
while [ true ] while [ true ]
do do
#Going to recovery shell should be authenticated if supported
gpg_auth
echo >&2 "!!!!! Starting recovery shell" echo >&2 "!!!!! Starting recovery shell"
sleep 1 sleep 1
@ -102,6 +263,57 @@ combine_configs() {
cat /etc/config* > /tmp/config cat /etc/config* > /tmp/config
} }
replace_config() {
TRACE "Under /etc/functions:replace_config"
CONFIG_FILE=$1
CONFIG_OPTION=$2
NEW_SETTING=$3
touch $CONFIG_FILE
# first pull out the existing option from the global config and place in a tmp file
awk "gsub(\"^export ${CONFIG_OPTION}=.*\",\"export ${CONFIG_OPTION}=\\\"${NEW_SETTING}\\\"\")" /tmp/config >${CONFIG_FILE}.tmp
awk "gsub(\"^${CONFIG_OPTION}=.*\",\"${CONFIG_OPTION}=\\\"${NEW_SETTING}\\\"\")" /tmp/config >>${CONFIG_FILE}.tmp
# then copy any remaining settings from the existing config file, minus the option you changed
grep -v "^export ${CONFIG_OPTION}=" ${CONFIG_FILE} | grep -v "^${CONFIG_OPTION}=" >>${CONFIG_FILE}.tmp || true
sort ${CONFIG_FILE}.tmp | uniq >${CONFIG_FILE}
rm -f ${CONFIG_FILE}.tmp
}
# Set a config variable in a specific file to a given value - replace it if it
# exists, or add it. If added, the variable will be exported.
set_config() {
CONFIG_FILE="$1"
CONFIG_OPTION="$2"
NEW_SETTING="$3"
if grep -q "$CONFIG_OPTION" "$CONFIG_FILE"; then
replace_config "$CONFIG_FILE" "$CONFIG_OPTION" "$NEW_SETTING"
else
echo "export $CONFIG_OPTION=\"$NEW_SETTING\"" >>"$CONFIG_FILE"
fi
}
# Set a value in config.user, re-combine configs, and update configs in the
# environment.
set_user_config() {
CONFIG_OPTION="$1"
NEW_SETTING="$2"
set_config /etc/config.user "$CONFIG_OPTION" "$NEW_SETTING"
combine_configs
. /tmp/config
}
# Load a config value to a variable, defaulting to empty. Does not fail if the
# config is not set (since it would expand to empty by default).
load_config_value() {
local config_name="$1"
if grep -q "$config_name=" /tmp/config; then
grep "$config_name=" /tmp/config | tail -n1 | cut -f2 -d '=' | tr -d '"'
fi
}
enable_usb() enable_usb()
{ {
TRACE "Under /etc/ash_functions:enable_usb" TRACE "Under /etc/ash_functions:enable_usb"

View File

@ -96,16 +96,15 @@ reseal_tpm_disk_decryption_key() {
fi fi
if [ -s /boot/kexec_key_devices.txt ] || [ -s /boot/kexec_key_lvm.txt ]; then if [ -s /boot/kexec_key_devices.txt ] || [ -s /boot/kexec_key_lvm.txt ]; then
warn "A TPM Disk Unlock Key previously sealed is now invalid since firmware measurements could not unseal TOTP" warn "TPM sealed Disk Unlock Key secret needs to be resealed alongside TOTP/HOTP secret"
echo "Renewing LUKS Disk Unlock Key to be unsealed by TPM Disk Unlock Key passphrase" echo "Resealing TPM LUKS Disk Unlock Key to be unsealed by TPM Disk Unlock Key passphrase"
while ! kexec-seal-key /boot; do while ! kexec-seal-key /boot; do
warn "Recovery Disk Encryption key passphrase invalid. Try again!" warn "Recovery Disk Encryption key passphrase/TPM Owner Password may be invalid. Please try again"
done done
warn "LUKS header hash changed under /boot/kexec_luks_hdr_hash.txt" warn "LUKS header hash changed under /boot/kexec_luks_hdr_hash.txt"
echo "Updating checksums and signing all files under /boot/kexec.sig" echo "Updating checksums and signing all files under /boot/kexec.sig"
while ! update_checksums; do while ! update_checksums; do
warn "Checksums were not signed. Bad GPG PIN provided?" warn "Checksums were not signed. Preceding errors should explain possible causes"
warn "Please update checksums and provide a valid GPG PIN"
done done
warn "Rebooting in 3 seconds to enable booting default boot option" warn "Rebooting in 3 seconds to enable booting default boot option"
sleep 3 sleep 3
@ -119,6 +118,7 @@ reseal_tpm_disk_decryption_key() {
# be detected. If USB storage was already enabled, no wait occurs, this would # be detected. If USB storage was already enabled, no wait occurs, this would
# have happened already when USB storage was enabled. # have happened already when USB storage was enabled.
enable_usb_storage() { enable_usb_storage() {
TRACE "Under /etc/functions:enable_usb_storage"
if ! lsmod | grep -q usb_storage; then if ! lsmod | grep -q usb_storage; then
timeout=0 timeout=0
echo "Scanning for USB storage devices..." echo "Scanning for USB storage devices..."
@ -189,83 +189,59 @@ list_usb_storage() {
done done
} }
confirm_gpg_card() { # Prompt for a TPM Owner Password if it is not already cached in /tmp/secret/tpm_owner_password.
TRACE "Under /etc/functions:confirm_gpg_card" # Sets tpm_owner_password variable reused in flow, and cache file used until recovery shell is accessed.
read \ # Tools should optionally accept a TPM password on the command line, since some flows need
-n 1 \ # it multiple times and only one prompt is ideal.
-p "Please confirm that your GPG card is inserted [Y/n]: " \ prompt_tpm_owner_password() {
card_confirm TRACE "Under /etc/functions:prompt_tpm_owner_password"
echo
if [ "$card_confirm" != "y" \ if [ -s /tmp/secret/tpm_owner_password ]; then
-a "$card_confirm" != "Y" \ DEBUG "/tmp/secret/tpm_owner_password already cached in file. Reusing"
-a -n "$card_confirm" ] \ tpm_owner_password=$(cat /tmp/secret/tpm_owner_password)
; then
die "gpg card not confirmed"
fi
# setup the USB so we can reach the GPG card
enable_usb
echo -e "\nVerifying presence of GPG card...\n"
# ensure we don't exit without retrying
errexit=$(set -o | grep errexit | awk '{print $2}')
set +e
gpg --card-status >/dev/null
if [ $? -ne 0 ]; then
# prompt for reinsertion and try a second time
read -n1 -r -p \
"Can't access GPG key; remove and reinsert, then press Enter to retry. " \
ignored
# restore prev errexit state
if [ "$errexit" = "on" ]; then
set -e
fi
# retry card status
gpg --card-status >/dev/null ||
die "gpg card read failed"
fi
# restore prev errexit state
if [ "$errexit" = "on" ]; then
set -e
fi
}
# Prompt for an owner password if it is not already set in tpm_password. Sets
# tpm_password. Tools should optionally accept a TPM password on the command
# line, since some flows need it multiple times and only one prompt is ideal.
prompt_tpm_password() {
if [ -n "$tpm_password" ]; then
return 0 return 0
fi fi
read -s -p "TPM Owner password: " tpm_password read -s -p "TPM Owner Password: " tpm_owner_password
echo # new line after password prompt echo # new line after password prompt
# Cache the password externally to be reused by who needs it
DEBUG "Caching TPM Owner Password to /tmp/secret/tpm_owner_password"
mkdir -p /tmp/secret || die "Unable to create /tmp/secret"
echo -n "$tpm_owner_password" >/tmp/secret/tpm_owner_password || die "Unable to cache TPM owner_password under /tmp/secret/tpm_owner_password"
} }
# Prompt for a new owner password when resetting the TPM. Returned in # Prompt for a new TPM Owner Password when resetting the TPM.
# key_password. The password must be 1-32 characters and must be entered twice, # Returned in tpm_owner_passpword and cached under /tpm/secret/tpm_owner_password
# The password must be 1-32 characters and must be entered twice,
# the script will loop until this is met. # the script will loop until this is met.
prompt_new_owner_password() { prompt_new_owner_password() {
local key_password2 TRACE "Under /etc/functions:prompt_new_owner_password"
key_password=1 local tpm_owner_password2
key_password2=2 tpm_owner_password=1
while [ "$key_password" != "$key_password2" ] || [ "${#key_password}" -gt 32 ] || [ -z "$key_password" ]; do tpm_owner_password2=2
read -s -p "New TPM owner passphrase (2 words suggested, 1-32 characters max): " key_password while [ "$tpm_owner_password" != "$tpm_owner_password2" ] || [ "${#tpm_owner_password}" -gt 32 ] || [ -z "$tpm_owner_password" ]; do
read -s -p "New TPM Owner Password (2 words suggested, 1-32 characters max): " tpm_owner_password
echo echo
read -s -p "Repeat chosen TPM owner passphrase: " key_password2 read -s -p "Repeat chosen TPM Owner Password: " tpm_owner_password2
echo echo
if [ "$key_password" != "$key_password2" ]; then if [ "$tpm_owner_password" != "$tpm_owner_password2" ]; then
echo "Passphrases entered do not match. Try again!" echo "Passphrases entered do not match. Try again!"
echo echo
fi fi
done done
# Cache the password externally to be reused by who needs it
DEBUG "Caching TPM Owner Password to /tmp/secret/tpm_owner_password"
mkdir -p /tmp/secret || die "Unable to create /tmp/secret"
echo -n "$tpm_owner_password" >/tmp/secret/tpm_owner_password || die "Unable to cache TPM password under /tmp/secret"
} }
check_tpm_counter() { check_tpm_counter() {
TRACE "Under /etc/functions:check_tpm_counter" TRACE "Under /etc/functions:check_tpm_counter"
LABEL=${2:-3135106223} LABEL=${2:-3135106223}
tpm_password="$3" tpm_password="$3"
# if the /boot.hashes file already exists, read the TPM counter ID # if the /boot.hashes file already exists, read the TPM counter ID
@ -274,13 +250,11 @@ check_tpm_counter() {
TPM_COUNTER=$(grep counter- "$1" | cut -d- -f2) TPM_COUNTER=$(grep counter- "$1" | cut -d- -f2)
else else
warn "$1 does not exist; creating new TPM counter" warn "$1 does not exist; creating new TPM counter"
prompt_tpm_password
tpmr counter_create \ tpmr counter_create \
-pwdo "$tpm_password" \
-pwdc '' \ -pwdc '' \
-la $LABEL | -la $LABEL |
tee /tmp/counter || tee /tmp/counter ||
die "Unable to create TPM counter" die "Unable to create TPM counter"
TPM_COUNTER=$(cut -d: -f1 </tmp/counter) TPM_COUNTER=$(cut -d: -f1 </tmp/counter)
fi fi
@ -299,7 +273,7 @@ increment_tpm_counter() {
TRACE "Under /etc/functions:increment_tpm_counter" TRACE "Under /etc/functions:increment_tpm_counter"
tpmr counter_increment -ix "$1" -pwdc '' | tpmr counter_increment -ix "$1" -pwdc '' |
tee /tmp/counter-$1 || tee /tmp/counter-$1 ||
die "Counter increment failed" die "TPM counter increment failed for rollback prevention. Please reset the TPM"
} }
check_config() { check_config() {
@ -360,40 +334,6 @@ replace_config() {
rm -f ${CONFIG_FILE}.tmp rm -f ${CONFIG_FILE}.tmp
} }
# Set a config variable in a specific file to a given value - replace it if it
# exists, or add it. If added, the variable will be exported.
set_config() {
CONFIG_FILE="$1"
CONFIG_OPTION="$2"
NEW_SETTING="$3"
if grep -q "$CONFIG_OPTION" "$CONFIG_FILE"; then
replace_config "$CONFIG_FILE" "$CONFIG_OPTION" "$NEW_SETTING"
else
echo "export $CONFIG_OPTION=\"$NEW_SETTING\"" >>"$CONFIG_FILE"
fi
}
# Set a value in config.user, re-combine configs, and update configs in the
# environment.
set_user_config() {
CONFIG_OPTION="$1"
NEW_SETTING="$2"
set_config /etc/config.user "$CONFIG_OPTION" "$NEW_SETTING"
combine_configs
. /tmp/config
}
# Load a config value to a variable, defaulting to empty. Does not fail if the
# config is not set (since it would expand to empty by default).
load_config_value() {
local config_name="$1"
if grep -q "$config_name=" /tmp/config; then
grep "$config_name=" /tmp/config | tail -n1 | cut -f2 -d '=' | tr -d '"'
fi
}
# Generate a secret for TPM-less HOTP by reading the ROM. Output is the # Generate a secret for TPM-less HOTP by reading the ROM. Output is the
# sha256sum of the ROM (binary, not printable), which can be truncated to the # sha256sum of the ROM (binary, not printable), which can be truncated to the
# supported secret length. # supported secret length.
@ -608,6 +548,7 @@ detect_boot_device() {
} }
scan_boot_options() { scan_boot_options() {
TRACE "Under /etc/functions:scan_boot_options"
local bootdir config option_file local bootdir config option_file
bootdir="$1" bootdir="$1"
config="$2" config="$2"

View File

@ -34,54 +34,100 @@ mount_usb()
fi fi
} }
# Create display text for a size in bytes in either MB or GB, unit selected
# automatically, rounded to nearest
display_size() {
local size_bytes unit_divisor unit_symbol
size_bytes="$1"
# If it's less than 1 GB, display MB
if [ "$((size_bytes))" -lt "$((1024*1024*1024))" ]; then
unit_divisor=$((1024*1024))
unit_symbol="MB"
else
unit_divisor=$((1024*1024*1024))
unit_symbol="GB"
fi
# Divide by the unit divisor and round to nearest
echo "$(( (size_bytes + unit_divisor/2) / unit_divisor )) $unit_symbol"
}
# Create display text for the size of a block device using MB or GB, rounded to
# nearest
display_block_device_size() {
local block_dev disk_size_bytes
block_dev="$1"
# Obtain size of thumb drive to be wiped with fdisk
if ! disk_size_bytes="$(blockdev --getsize64 "$block_dev")"; then
exit 1
fi
display_size "$disk_size_bytes"
}
# Display a menu to select a file from a list. Pass the name of a file
# containing the list.
# --show-size: Append sizes of files listed. Currently only supports block
# devices.
# $1: Name of file listing files that can be chosen (one per line)
# $2: Optional prompt message
# $3: Optional prompt title
#
# Success: Sets FILE with the selected file
# User aborted: Exits successfully with FILE empty
# No entries in list: Displays error and exits unsuccessfully
file_selector() file_selector()
{ {
TRACE "under gui_functions:file_selector" TRACE "under gui_functions:file_selector"
FILE=""
FILE_LIST=$1
MENU_MSG=${2:-"Choose the file"}
MENU_TITLE=${3:-"Select your File"}
# create file menu options local FILE_LIST MENU_MSG MENU_TITLE CHOICE_ARGS SHOW_SIZE OPTION_SIZE option_index
if [ `cat "$FILE_LIST" | wc -l` -gt 0 ]; then
option=""
while [ -z "$option" ]
do
MENU_OPTIONS=""
n=0
while read option
do
n=`expr $n + 1`
option=$(echo $option | tr " " "_")
MENU_OPTIONS="$MENU_OPTIONS $n ${option}"
done < $FILE_LIST
MENU_OPTIONS="$MENU_OPTIONS a Abort" FILE=""
whiptail --title "${MENU_TITLE}" \
--menu "${MENU_MSG} [1-$n, a to abort]:" 20 120 8 \
-- $MENU_OPTIONS \
2>/tmp/whiptail || die "Aborting"
option_index=$(cat /tmp/whiptail) if [ "$1" = "--show-size" ]; then
SHOW_SIZE=y
shift
fi
if [ "$option_index" = "a" ]; then FILE_LIST=$1
option="a" MENU_MSG=${2:-"Choose the file"}
return MENU_TITLE=${3:-"Select your File"}
fi
option=`head -n $option_index $FILE_LIST | tail -1` CHOICE_ARGS=()
if [ "$option" == "a" ]; then n=0
return while read option; do
fi n="$((++n))"
done
if [ -n "$option" ]; then if [ "$SHOW_SIZE" = "y" ] && OPTION_SIZE="$(display_block_device_size "$option")"; then
FILE=$option option="$option - $OPTION_SIZE"
fi fi
else CHOICE_ARGS+=("$n" "$option")
whiptail $BG_COLOR_ERROR --title 'ERROR: No Files Found' \ done < "$FILE_LIST"
--msgbox "No Files found matching the pattern. Aborting." 0 80
exit 1 if [ "${#CHOICE_ARGS[@]}" -eq 0 ]; then
fi whiptail $BG_COLOR_ERROR --title 'ERROR: No Files Found' \
--msgbox "No Files found matching the pattern. Aborting." 0 80
exit 1
fi
CHOICE_ARGS+=(a Abort)
# create file menu options
option_index=""
while [ -z "$option_index" ]; do
whiptail --title "${MENU_TITLE}" \
--menu "${MENU_MSG} [1-$n, a to abort]:" 20 120 8 \
-- "${CHOICE_ARGS[@]}" \
2>/tmp/whiptail || die "Aborting"
option_index=$(cat /tmp/whiptail)
if [ "$option_index" != "a" ]; then
FILE="$(head -n "$option_index" "$FILE_LIST" | tail -1)"
fi
done
} }
show_system_info() show_system_info()

View File

@ -6,25 +6,19 @@
. /tmp/config . /tmp/config
#List all LUKS devices on the system #List all LUKS devices on the system
list_luks_devices() list_luks_devices() {
{
#generate a list of devices to choose from that contain a LUKS header #generate a list of devices to choose from that contain a LUKS header
lvm vgscan||true lvm vgscan || true
blkid | cut -d ':' -f 1 | while read device blkid | cut -d ':' -f 1 | while read device; do
do cryptsetup isLuks $device if cryptsetup isLuks $device; then echo $device; fi
if [ $? -eq 0 ]; then done | sort
echo "$device"
fi
done | sort
} }
#Whiptail prompt asking user to select ratio of device to use for LUKS container between: 25, 50, 75
#Whiptail prompt asking user to select ratio of device to use for LUKS container between: 10, 25, 50, 75 select_luks_container_size_percent() {
select_luks_container_size_percent()
{
TRACE "Under /etc/luks-functions:select_luks_container_size_percent()" TRACE "Under /etc/luks-functions:select_luks_container_size_percent()"
if [ -x /bin/whiptail ]; then if [ -x /bin/whiptail ]; then
#whiptail prompt asking user to select ratio of device to use for LUKS container between: 10, 25, 50, 75 #whiptail prompt asking user to select ratio of device to use for LUKS container between: 25, 50, 75
#whiptail returns the percentage of the device to use for LUKS container #whiptail returns the percentage of the device to use for LUKS container
whiptail --title "Select LUKS container size percentage of device" --menu \ whiptail --title "Select LUKS container size percentage of device" --menu \
"Select LUKS container size percentage of device:" 0 80 10 \ "Select LUKS container size percentage of device:" 0 80 10 \
@ -57,11 +51,12 @@ select_luks_container_size_percent()
fi fi
} }
#Partition a device with two partitions: a first one being a LUKS container containing private ext4 partition and second public exfat partition # Partition a device interactively with two partitions: a LUKS container
# containing private ext4 partition and second public exFAT partition
# Size provisioning is done by percentage of the device # Size provisioning is done by percentage of the device
prepare_thumb_drive() interactive_prepare_thumb_drive()
{ {
TRACE "Under /etc/luks-functions:prepare_thumb_drive()" TRACE "Under /etc/luks-functions:interactive_prepare_thumb_drive()"
#Refactoring: only one parameter needed to be prompted for: the passphrase for LUKS container if not coming from oem-provisioning #Refactoring: only one parameter needed to be prompted for: the passphrase for LUKS container if not coming from oem-provisioning
#If no passphrase was provided, ask user to select passphrase for LUKS container #If no passphrase was provided, ask user to select passphrase for LUKS container
# if no device provided as parameter, we will ask user to select device to partition # if no device provided as parameter, we will ask user to select device to partition
@ -84,12 +79,13 @@ prepare_thumb_drive()
PERCENTAGE=$2 PERCENTAGE=$2
shift 2 shift 2
;; ;;
--passphrase) --pass)
PASSPHRASE=$2 PASSPHRASE=$2
shift 2 shift 2
;; ;;
*) *)
echo "usage: prepare_thumb_drive [--device device] [--percentage percentage] [--passphrase passphrase]" echo "usage: prepare_thumb_drive [--device device] [--percentage percentage] [--pass passphrase]"
return 1
;; ;;
esac esac
done done
@ -177,37 +173,82 @@ prepare_thumb_drive()
PERCENTAGE=$(cat /tmp/luks_container_size_percent) PERCENTAGE=$(cat /tmp/luks_container_size_percent)
fi fi
confirm_thumb_drive_format "$DEVICE" "$PERCENTAGE" ||
die "User cancelled wiping and repartitioning of $DEVICE"
#Get disk size in bytes from fdisk prepare_thumb_drive "$DEVICE" "$PERCENTAGE" "$PASSPHRASE"
}
# Show a prompt to confirm formatting a flash drive with a percentage allocated
# to LUKS. interactive_prepare_thumb_drive() uses this; during OEM reset it is
# used separately before performing any reset actions
#
# parameters:
# $1 - block device of flash drive
# $2 - percent of device allocated to LUKS [1-99]
confirm_thumb_drive_format()
{
TRACE "Under /etc/luks-functions:confirm_thumb_drive_format()"
local DEVICE LUKS_PERCENTAGE DISK_SIZE_BYTES DISK_SIZE_DISPLAY LUKS_PERCENTAGE LUKS_SIZE_MB MSG
DEVICE="$1"
LUKS_PERCENTAGE="$2"
LUKS_SIZE_MB=
#Get disk size in bytes
DISK_SIZE_BYTES="$(blockdev --getsize64 "$DEVICE")" DISK_SIZE_BYTES="$(blockdev --getsize64 "$DEVICE")"
DISK_SIZE_DISPLAY="$(display_size "$DISK_SIZE_BYTES")"
#Convert disk size to MB #Convert disk size to MB
DISK_SIZE_MB=$((DISK_SIZE_BYTES/1024/1024)) DISK_SIZE_MB=$((DISK_SIZE_BYTES/1024/1024))
#Get size in bytes from percentage and apply percentage to DISK_SIZE_MB #Calculate percentage of device in MB
PERCENTAGE_MB="$((DISK_SIZE_MB*PERCENTAGE/100))" LUKS_SIZE_MB="$((DISK_SIZE_BYTES*LUKS_PERCENTAGE/100/1024/1024))"
#Console and whiptail $BG_COLOR_WARNING prompt (Y/n) validate one last time wiping and repartitioning of $device of total size $DISK_SIZE_MB with $PERCENTAGE_MB assigned to LUKS encrypted private partition MSG="WARNING: Wiping and repartitioning $DEVICE ($DISK_SIZE_DISPLAY) with $LUKS_SIZE_MB MB\n assigned to private LUKS ext4 partition,\n rest assigned to exFAT public partition.\n\nAre you sure you want to continue?"
if [ -x /bin/whiptail ]; then if [ -x /bin/whiptail ]; then
whiptail $BG_COLOR_WARNING --title "WARNING: Wiping and repartitioning $DEVICE of $DISK_SIZE_MB MB" --yesno \ whiptail $BG_COLOR_WARNING --title "WARNING: Wiping and repartitioning $DEVICE ($DISK_SIZE_DISPLAY)" --yesno \
"WARNING: Wiping and repartitioning $DEVICE with $PERCENTAGE_MB MB assigned to private LUKS contained private ext4 partition, rest assigned to extfat public partition.\n\nAre you sure you want to continue?" 0 80 \ "$MSG" 0 80
|| die "User cancelled wiping and repartitioning of $DEVICE"
else else
echo -e -n "Warning: Wiping and repartitioning $DEVICE with $PERCENTAGE_MB MB assigned to private LUKS contained private ext4 partition, rest assigned to extfat public partition.\n\nAre you sure you want to continue?" echo -e -n "$MSG"
read -r -p " [Y/n] " response read -r -p " [Y/n] " response
#transform response to uppercase with bash parameter expansion #transform response to uppercase with bash parameter expansion
response=${response^^} response=${response^^}
#continue if response different then uppercase N #continue if response is Y, y, or empty, abort for anything else
if [[ $response =~ ^(N)$ ]]; then if [ -n "$response" ] && [ "${response^^}" != Y ]; then
die "User cancelled wiping and repartitioning of $DEVICE" return 1
fi fi
fi fi
}
echo -e "Preparing $DEVICE with $PERCENTAGE_MB MB for private LUKS container and rest of disk with exfat\ # Prepare a flash drive with a private LUKS-encrypted ext4 partition and a
\n for public partition (This may take a while)..." | fold -s # public exFAT partition. This is not interactive - during OEM reset, any
# selections/confirmations must occur before OEM reset starts resetting the
# system.
#
# $1 - block device of flash drive
# $2 - percentage of flash drive to allocate to LUKS [1-99]
# $3 - passphrase for LUKS container
prepare_thumb_drive()
{
TRACE "Under /etc/luks-functions:prepare_thumb_drive()"
local DEVICE PERCENTAGE PASSPHRASE DISK_SIZE_BYTES PERCENTAGE_MB
DEVICE="$1"
PERCENTAGE="$2"
PASSPHRASE="$3"
#Get disk size in bytes
DISK_SIZE_BYTES="$(blockdev --getsize64 "$DEVICE")"
#Calculate percentage of device in MB
PERCENTAGE_MB="$((DISK_SIZE_BYTES*PERCENTAGE/100/1024/1024))"
echo -e "Preparing $DEVICE with $PERCENTAGE_MB MB for private LUKS container while rest of device will be assigned to exFAT public partition...\n"
echo "Please wait..."
DEBUG "Creating empty DOS partition table on device through fdisk to start clean" DEBUG "Creating empty DOS partition table on device through fdisk to start clean"
echo -e "o\nw\n" | fdisk $DEVICE > /dev/null 2>&1 || die "Error creating partition table" echo -e "o\nw\n" | fdisk $DEVICE >/dev/null 2>&1 || die "Error creating partition table"
DEBUG "partition device with two partitions: first one being the percent applied and rest for second partition through fdisk" DEBUG "partition device with two partitions: first one being the percent applied and rest for second partition through fdisk"
echo -e "n\np\n1\n\n+"$PERCENTAGE_MB"M\nn\np\n2\n\n\nw\n" | fdisk $DEVICE > /dev/null 2>&1 || die "Error partitioning device" echo -e "n\np\n1\n\n+"$PERCENTAGE_MB"M\nn\np\n2\n\n\nw\n" | fdisk $DEVICE >/dev/null 2>&1 || die "Error partitioning device"
DEBUG "cryptsetup luksFormat first partition with LUKS container aes-xts-plain64 cipher with sha256 hash and 512 bit key" DEBUG "cryptsetup luksFormat first partition with LUKS container aes-xts-plain64 cipher with sha256 hash and 512 bit key"
DEBUG "Creating ${PERCENTAGE_MB}MB LUKS container on ${DEVICE}1..." DEBUG "Creating ${PERCENTAGE_MB}MB LUKS container on ${DEVICE}1..."
DO_WITH_DEBUG cryptsetup --batch-mode -c aes-xts-plain64 -h sha256 -s 512 -y luksFormat ${DEVICE}1 \ DO_WITH_DEBUG cryptsetup --batch-mode -c aes-xts-plain64 -h sha256 -s 512 -y luksFormat ${DEVICE}1 \
--key-file <(echo -n "${PASSPHRASE}") > /dev/null 2>&1 \ --key-file <(echo -n "${PASSPHRASE}") > /dev/null 2>&1 \
@ -216,11 +257,11 @@ prepare_thumb_drive()
DO_WITH_DEBUG cryptsetup open ${DEVICE}1 private --key-file <(echo -n "${PASSPHRASE}") > /dev/null 2>&1 \ DO_WITH_DEBUG cryptsetup open ${DEVICE}1 private --key-file <(echo -n "${PASSPHRASE}") > /dev/null 2>&1 \
|| die "Error opening LUKS container" || die "Error opening LUKS container"
DEBUG "Formatting LUKS container mapped under /dev/mapper/private as an ext4 partition..." DEBUG "Formatting LUKS container mapped under /dev/mapper/private as an ext4 partition..."
mke2fs -t ext4 -L private /dev/mapper/private > /dev/null 2>&1 || die "Error formatting LUKS container's ext4 filesystem" mke2fs -t ext4 -L private /dev/mapper/private >/dev/null 2>&1 || die "Error formatting LUKS container's ext4 filesystem"
DEBUG "Closing LUKS device /dev/mapper/private..." DEBUG "Closing LUKS device /dev/mapper/private..."
cryptsetup close private > /dev/null 2>&1 || die "Error closing LUKS container" cryptsetup close private > /dev/null 2>&1 || die "Error closing LUKS container"
DEBUG "Formatting second partition ${DEVICE}2 with exfat filesystem..." DEBUG "Formatting second partition ${DEVICE}2 with exfat filesystem..."
mkfs.exfat -L public ${DEVICE}2 > /dev/null 2>&1 || die "Error formatting second partition with exfat filesystem" mkfs.exfat -L public ${DEVICE}2 >/dev/null 2>&1 || die "Error formatting second partition with exfat filesystem"
echo "Done." echo "Done."
} }
@ -242,11 +283,11 @@ select_luks_container()
LUKS=$FILE LUKS=$FILE
detect_boot_device detect_boot_device
mount -o remount,rw /boot mount -o remount,rw /boot
echo "$LUKS $(cryptsetup luksUUID $LUKS)" > /boot/kexec_key_devices.txt echo "$LUKS $(cryptsetup luksUUID $LUKS)" >/boot/kexec_key_devices.txt
mount -o remount,ro /boot mount -o remount,ro /boot
fi fi
else else
warn "No encrypted device found." warn "No encrypted device found"
return 1 return 1
fi fi
fi fi
@ -255,17 +296,17 @@ select_luks_container()
test_luks_current_disk_recovery_key_passphrase() test_luks_current_disk_recovery_key_passphrase()
{ {
TRACE "Under /etc/luks-functions:test_luks_current_disk_recovery_key_passphrase()" TRACE "Under /etc/luks-functions:test_luks_current_disk_recovery_key_passphrase()"
while : ; do while :; do
select_luks_container || return 1 select_luks_container || return 1
if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ]; then if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ]; then
#if no external provisioning provides current Disk Recovery Key passphrase #if no external provisioning provides current Disk Recovery Key passphrase
echo -e "\nEnter current Disk Recovery Key passphrase (Provisioned at OS installation or by OEM):" echo -e "\nEnter current Disk Recovery Key passphrase (Configured at OS installation or by OEM):"
read -r luks_current_Disk_Recovery_Key_passphrase read -r luks_current_Disk_Recovery_Key_passphrase
echo -n "$luks_current_Disk_Recovery_Key_passphrase" > /tmp/luks_current_Disk_Recovery_Key_passphrase echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/luks_current_Disk_Recovery_Key_passphrase
warn "Test opening "$LUKS" LUKS encrypted drive content with current Recovery Disk Key passphrase..." warn "Test opening "$LUKS" LUKS encrypted drive content with current Recovery Disk Key passphrase..."
cryptsetup open $LUKS test --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase cryptsetup open $LUKS test --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase
else else
echo -n "$luks_current_Disk_Recovery_Key_passphrase" > /tmp/luks_current_Disk_Recovery_Key_passphrase echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/luks_current_Disk_Recovery_Key_passphrase
warn "Test opening "$LUKS" LUKS encrypted drive content with current Recovery Disk Key passphrase..." warn "Test opening "$LUKS" LUKS encrypted drive content with current Recovery Disk Key passphrase..."
cryptsetup open $LUKS test --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase cryptsetup open $LUKS test --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase
fi fi
@ -273,10 +314,10 @@ test_luks_current_disk_recovery_key_passphrase()
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
whiptail --title 'Invalid Actual LUKS Disk Recovery Key passphrase?' --msgbox \ whiptail --title 'Invalid Actual LUKS Disk Recovery Key passphrase?' --msgbox \
"If you previously changed it and do not remember it, you will have to\n reinstall OS from a an external drive.\n\nTo do so, place ISO file and its signature file on root of external drive,\n and select Options-> Boot from USB \n\nHit Enter to retry." 30 60 "If you previously changed it and do not remember it, you will have to\n reinstall OS from a an external drive.\n\nTo do so, place ISO file and its signature file on root of external drive,\n and select Options-> Boot from USB \n\nHit Enter to retry." 30 60
shred -n 10 -z -u /tmp/luks_current_Disk_Recovery_Key_passphrase 2> /dev/null shred -n 10 -z -u /tmp/luks_current_Disk_Recovery_Key_passphrase 2>/dev/null
#unsetting luks_current_Disk_Recovery_Key_passphrase so we prompt for it again Disk Recovery Key passphrase prompt on next round #unsetting luks_current_Disk_Recovery_Key_passphrase so we prompt for it again Disk Recovery Key passphrase prompt on next round
unset luks_current_Disk_Recovery_Key_passphrase unset luks_current_Disk_Recovery_Key_passphrase
#remove "known good" selected luks container so that next pass asks again user to select luks container. #remove "known good" selected LUKS container so that next pass asks again user to select LUKS container.
#maybe the container was not the right one #maybe the container was not the right one
detect_boot_device detect_boot_device
mount -o remount,rw /boot mount -o remount,rw /boot
@ -294,108 +335,108 @@ test_luks_current_disk_recovery_key_passphrase()
done done
} }
luks_reencrypt(){ luks_reencrypt() {
TRACE "Under /etc/luks-functions:luks_reencrypt()" TRACE "Under /etc/luks-functions:luks_reencrypt()"
while : ; do while :; do
select_luks_container || return 1 select_luks_container || return 1
if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ]; then if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ]; then
#if no external provisioning provides current Disk Recovery Key passphrase #if no external provisioning provides current Disk Recovery Key passphrase
whiptail --title 'Reencrypt LUKS disk encrypted container ?' \ whiptail --title 'Reencrypt LUKS disk encrypted container ?' \
--msgbox "This will replace the encrypted container content and its Disk Recovery Key.\n\nThe passphrase associated with this key will be asked from the user in the\nfollowing conditions:\n 1-Every boot if no Disk unlock key was added to the TPM\n 2-If the TPM fails (Hardware failure)\n 3-If the firmware has been tampered with/upgraded/modified by the user\n\nThis process requires you to type the current Disk Recovery Key passphrase\nand will delete TPM Disk unlock key slot if set up by setting a default boot\n LUKS header (slot 1) if present.\n\nAt the next prompt, you may be asked to select which file corresponds to\nthe LUKS device container.\n\nHit Enter to continue." 0 80 --msgbox "This will replace the encrypted container content and its Disk Recovery Key.\n\nThe passphrase associated with this key will be asked from the user in the\nfollowing conditions:\n 1-Every boot if no Disk unlock key was added to the TPM\n 2-If the TPM fails (Hardware failure)\n 3-If the firmware has been tampered with/upgraded/modified by the user\n\nThis process requires you to type the current Disk Recovery Key passphrase\nand will delete TPM Disk unlock key slot if set up by setting a default boot\n LUKS header (slot 1) if present.\n\nAt the next prompt, you may be asked to select which file corresponds to\nthe LUKS device container.\n\nHit Enter to continue." 0 80
echo -e "\nEnter current Disk Recovery Key passphrase (Provisioned at OS installation or by OEM):" echo -e "\nEnter current Disk Recovery Key passphrase (Configured at OS installation or by OEM):"
read -r luks_current_Disk_Recovery_Key_passphrase read -r luks_current_Disk_Recovery_Key_passphrase
echo -n "$luks_current_Disk_Recovery_Key_passphrase" > /tmp/luks_current_Disk_Recovery_Key_passphrase echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/luks_current_Disk_Recovery_Key_passphrase
warn "Reencrypting "$LUKS" LUKS encrypted drive content with current Recovery Disk Key passphrase..." warn "Reencrypting "$LUKS" LUKS encrypted drive content with current Recovery Disk Key passphrase..."
cryptsetup-reencrypt -B 64 --use-directio "$LUKS" --key-slot 0 --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase cryptsetup-reencrypt -B 64 --use-directio "$LUKS" --key-slot 0 --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase
else else
echo -n "$luks_current_Disk_Recovery_Key_passphrase" > /tmp/luks_current_Disk_Recovery_Key_passphrase echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/luks_current_Disk_Recovery_Key_passphrase
warn "Reencrypting "$LUKS" LUKS encrypted drive content with current Recovery Disk Key passphrase..." warn "Reencrypting "$LUKS" LUKS encrypted drive content with current Recovery Disk Key passphrase..."
cryptsetup-reencrypt -B 64 --use-directio "$LUKS" --key-slot 0 --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase cryptsetup-reencrypt -B 64 --use-directio "$LUKS" --key-slot 0 --key-file /tmp/luks_current_Disk_Recovery_Key_passphrase
fi fi
#Validate past cryptsetup-reencrypt attempts #Validate past cryptsetup-reencrypt attempts
if [ $(echo $?) -ne 0 ]; then if [ $(echo $?) -ne 0 ]; then
whiptail --title 'Invalid Actual LUKS Disk Recovery Key passphrase?' --msgbox \ whiptail --title 'Invalid Actual LUKS Disk Recovery Key passphrase?' --msgbox \
"If you previously changed it and do not remember it, you will have to\n reinstall OS from a an external drive.\n\nTo do so, place ISO file and its signature file on root of external drive,\n and select Options-> Boot from USB \n\nHit Enter to retry." 30 60 "If you previously changed it and do not remember it, you will have to\n reinstall OS from a an external drive.\n\nTo do so, place ISO file and its signature file on root of external drive,\n and select Options-> Boot from USB \n\nHit Enter to retry." 30 60
shred -n 10 -z -u /tmp/luks_current_Disk_Recovery_Key_passphrase 2> /dev/null shred -n 10 -z -u /tmp/luks_current_Disk_Recovery_Key_passphrase 2>/dev/null
#unsetting luks_current_Disk_Recovery_Key_passphrase so we prompt for it again Disk Recovery Key passphrase prompt on next round #unsetting luks_current_Disk_Recovery_Key_passphrase so we prompt for it again Disk Recovery Key passphrase prompt on next round
unset luks_current_Disk_Recovery_Key_passphrase unset luks_current_Disk_Recovery_Key_passphrase
#remove "known good" selected luks container so that next pass asks again user to select luks container. #remove "known good" selected LUKS container so that next pass asks again user to select LUKS container.
#maybe the container was not the right one #maybe the container was not the right one
detect_boot_device detect_boot_device
mount -o remount,rw /boot mount -o remount,rw /boot
rm -f /boot/kexec_key_devices.txt rm -f /boot/kexec_key_devices.txt
mount -o remount,ro /boot mount -o remount,ro /boot
else else
#Reencryption was successful. Cleanup should be called only when done #Reencryption was successful. Cleanup should be called only when done
#Exporting successfully used passphrase possibly reused by oem-factory-reset #Exporting successfully used passphrase possibly reused by oem-factory-reset
export luks_current_Disk_Recovery_Key_passphrase export luks_current_Disk_Recovery_Key_passphrase
break; break;
fi fi
done done
} }
luks_change_passphrase() luks_change_passphrase()
{ {
TRACE "Under /etc/luks-functions:luks_change_passphrase()" TRACE "Under /etc/luks-functions:luks_change_passphrase()"
while : ; do while :; do
select_luks_container || return 1 select_luks_container || return 1
#if actual or new Disk Recovery Key is not provisioned by oem-provisioning file #if actual or new Disk Recovery Key is not provisioned by oem-provisioning file
if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ] || [ -z "$luks_new_Disk_Recovery_Key_passphrase" ] ; then if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ] || [ -z "$luks_new_Disk_Recovery_Key_passphrase" ]; then
whiptail --title 'Changing LUKS Disk Recovery Key passphrase' --msgbox \ whiptail --title 'Changing LUKS Disk Recovery Key passphrase' --msgbox \
"Please enter current Disk Recovery Key passphrase (slot 0).\nThen choose a strong passphrase of your own.\n\n**DICEWARE passphrase methodology is STRONGLY ADVISED.**\n\nHit Enter to continue" 30 60 "Please enter current Disk Recovery Key passphrase (slot 0).\nThen choose a strong passphrase of your own.\n\n**DICEWARE passphrase methodology is STRONGLY ADVISED.**\n\nHit Enter to continue" 30 60
if [ -z "$luks_new_Disk_Recovery_Key_passphrase" ] ; then if [ -z "$luks_new_Disk_Recovery_Key_passphrase" ]; then
echo -e "\nEnter desired replacement for actual Disk Recovery Key passphrase (At least 8 characters long):" echo -e "\nEnter desired replacement for actual Disk Recovery Key passphrase (At least 8 characters long):"
while [[ ${#luks_new_Disk_Recovery_Key_passphrase} -lt 8 ]]; do while [[ ${#luks_new_Disk_Recovery_Key_passphrase} -lt 8 ]]; do
{ {
read -r luks_new_Disk_Recovery_Key_passphrase read -r luks_new_Disk_Recovery_Key_passphrase
};done };done
fi
if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ]; then
echo -e "\nEnter current Disk Recovery Key passphrase (Configured at OS installation or by OEM):"
read -r luks_current_Disk_Recovery_Key_passphrase
fi
export luks_current_Disk_Recovery_Key_passphrase
export luks_new_Disk_Recovery_Key_passphrase
echo -n "$luks_new_Disk_Recovery_Key_passphrase" >/tmp/luks_new_Disk_Recovery_Key_passphrase
echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/luks_current_Disk_Recovery_Key_passphrase
warn "Changing "$LUKS" LUKS encrypted disk passphrase to new Disk Recovery Key passphrase..."
cryptsetup luksChangeKey "$LUKS" --key-slot 0 --key-file=/tmp/luks_current_Disk_Recovery_Key_passphrase /tmp/luks_new_Disk_Recovery_Key_passphrase
else
#If current and new Disk Recovery Key were exported
echo -n "$luks_new_Disk_Recovery_Key_passphrase" >/tmp/luks_new_Disk_Recovery_Key_passphrase
echo -n "$luks_current_Disk_Recovery_Key_passphrase" >/tmp/luks_current_Disk_Recovery_Key_passphrase
warn "Changing "$LUKS" LUKS encrypted disk passphrase to new Disk Recovery Key passphrase..."
cryptsetup luksChangeKey "$LUKS" --key-slot 0 --key-file=/tmp/luks_current_Disk_Recovery_Key_passphrase /tmp/luks_new_Disk_Recovery_Key_passphrase
fi fi
if [ -z "$luks_current_Disk_Recovery_Key_passphrase" ];then
echo -e "\nEnter current Disk Recovery Key passphrase (Provisioned at OS installation or by OEM):"
read -r luks_current_Disk_Recovery_Key_passphrase
fi
export luks_current_Disk_Recovery_Key_passphrase
export luks_new_Disk_Recovery_Key_passphrase
echo -n "$luks_new_Disk_Recovery_Key_passphrase" > /tmp/luks_new_Disk_Recovery_Key_passphrase
echo -n "$luks_current_Disk_Recovery_Key_passphrase" > /tmp/luks_current_Disk_Recovery_Key_passphrase
warn "Changing "$LUKS" LUKS encrypted disk passphrase to new Disk Recovery Key passphrase..."
cryptsetup luksChangeKey "$LUKS" --key-slot 0 --key-file=/tmp/luks_current_Disk_Recovery_Key_passphrase /tmp/luks_new_Disk_Recovery_Key_passphrase
else
#If current and new Disk Recovery Key were exported
echo -n "$luks_new_Disk_Recovery_Key_passphrase" > /tmp/luks_new_Disk_Recovery_Key_passphrase
echo -n "$luks_current_Disk_Recovery_Key_passphrase" > /tmp/luks_current_Disk_Recovery_Key_passphrase
warn "Changing "$LUKS" LUKS encrypted disk passphrase to new Disk Recovery Key passphrase..."
cryptsetup luksChangeKey "$LUKS" --key-slot 0 --key-file=/tmp/luks_current_Disk_Recovery_Key_passphrase /tmp/luks_new_Disk_Recovery_Key_passphrase
fi
#Validate past cryptsetup attempts #Validate past cryptsetup attempts
if [ $(echo $?) -ne 0 ]; then if [ $(echo $?) -ne 0 ]; then
#Cryptsetup luksChangeKey was unsuccessful #Cryptsetup luksChangeKey was unsuccessful
whiptail --title 'Invalid LUKS passphrase?' --msgbox \ whiptail --title 'Invalid LUKS passphrase?' --msgbox \
"The LUKS Disk Recovery Key passphrase was provided to you by the OEM over\n secure communication channel.\n\nIf you previously changed it and do not remember it,\n you will have to reinstall OS from a USB drive.\nTo do so, put OS ISO file and it's signature file on root of USB drive,\n And select Boot from USB\n\nHit Enter to continue." 30 60 "The LUKS Disk Recovery Key passphrase was provided to you by the OEM over\n secure communication channel.\n\nIf you previously changed it and do not remember it,\n you will have to reinstall OS from a USB drive.\nTo do so, put OS ISO file and it's signature file on root of USB drive,\n And select Boot from USB\n\nHit Enter to continue." 30 60
unset luks_current_Disk_Recovery_Key_passphrase unset luks_current_Disk_Recovery_Key_passphrase
unset luks_new_Disk_Recovery_Key_passphrase unset luks_new_Disk_Recovery_Key_passphrase
#remove "known good" selected luks container so that next pass asks again user to select LUKS container. #remove "known good" selected LUKS container so that next pass asks again user to select LUKS container.
#maybe the container was not the right one #maybe the container was not the right one
detect_boot_device detect_boot_device
mount -o remount,rw /boot mount -o remount,rw /boot
rm -f /boot/kexec_key_devices.txt rm -f /boot/kexec_key_devices.txt
mount -o remount,ro /boot mount -o remount,ro /boot
else else
#Cryptsetup was successful. #Cryptsetup was successful.
#Cleanup should be called seperately. #Cleanup should be called seperately.
#Exporting successfully used passphrase possibly reused by oem-factory-reset #Exporting successfully used passphrase possibly reused by oem-factory-reset
export luks_new_Disk_Recovery_Key_passphrase export luks_new_Disk_Recovery_Key_passphrase
break; break;
fi fi
done done
} }
luks_secrets_cleanup() luks_secrets_cleanup()
{ {
#Cleanup #Cleanup
shred -n 10 -z -u /tmp/luks_new_Disk_Recovery_Key_passphrase 2> /dev/null || true shred -n 10 -z -u /tmp/luks_new_Disk_Recovery_Key_passphrase 2>/dev/null || true
shred -n 10 -z -u /tmp/luks_current_Disk_Recovery_Key_passphrase 2> /dev/null || true shred -n 10 -z -u /tmp/luks_current_Disk_Recovery_Key_passphrase 2>/dev/null || true
unset luks_current_Disk_Recovery_Key_passphrase unset luks_current_Disk_Recovery_Key_passphrase
unset luks_new_Disk_Recovery_Key_passphrase unset luks_new_Disk_Recovery_Key_passphrase
} }

View File

@ -60,6 +60,14 @@ if [ "$CONFIG_DEBUG_OUTPUT" = "y" ]; then
#DEBUG and TRACE calls will output to /dev/kmsg, outputting both on dmesg and on console #DEBUG and TRACE calls will output to /dev/kmsg, outputting both on dmesg and on console
dmesg -n 8 || true dmesg -n 8 || true
DEBUG "Debug output enabled from board CONFIG_DEBUG_OUTPUT=y option (/etc/config)" DEBUG "Debug output enabled from board CONFIG_DEBUG_OUTPUT=y option (/etc/config)"
else
# Board config did't have CONFIG_DEBUG_OUTPUT=y defined
# config.user extracted and combined from CBFS had CONFIG_DEBUG_OUTPUT=y
# Output only print messages with a priority of 4 (warnings) or lower (errors and critical) kernel messages to console
# This way, "debug" kernel command line option will have all kernel messages output on console prior of this point
# This is useful to debug boot issues but permits qemu board to boot without flooding console with kernel messages by disabling CONFIG_DEBUG_OUTPUT=y in qemu board config
dmesg -n 4 || true
DEBUG "Debug output enabled from /etc/config.user's CONFIG_DEBUG_OUTPUT=y after combine_configs (Config menu enabled Debug)"
fi fi
TRACE "Under init" TRACE "Under init"
@ -160,6 +168,11 @@ if [ "$boot_option" = "r" ]; then
recovery 'User requested recovery shell' recovery 'User requested recovery shell'
# just in case... # just in case...
exit exit
elif [ "$boot_option" = "o" ]; then
# Launch OEM Factory Reset/Re-Ownership
oem-factory-reset
# just in case...
exit
fi fi
if [ "$CONFIG_BASIC" = "y" ]; then if [ "$CONFIG_BASIC" = "y" ]; then

View File

@ -30,16 +30,16 @@ if [ ! -r /sys/class/tpm/tpm0/pcrs -o ! -x /bin/tpm ]; then
fi fi
if [ -z "$tpm_missing" ]; then if [ -z "$tpm_missing" ]; then
DEBUG "Extending PCR $MODULE_PCR with $MODULE" DEBUG "Extending TPM PCR $MODULE_PCR with $MODULE prior of usage"
tpmr extend -ix "$MODULE_PCR" -if "$MODULE" \ tpmr extend -ix "$MODULE_PCR" -if "$MODULE" \
|| die "$MODULE: tpm extend failed" || die "$MODULE: tpm extend failed"
fi fi
if [ ! -z "$*" -a -z "$tpm_missing" ]; then if [ ! -z "$*" -a -z "$tpm_missing" ]; then
DEBUG "Extending PCR $MODULE_PCR with $*" DEBUG "Extending TPM PCR $MODULE_PCR with $*"
TMPFILE=/tmp/insmod.$$ TMPFILE=/tmp/insmod.$$
echo "$@" > $TMPFILE echo "$@" > $TMPFILE
DEBUG "Extending PCR $MODULE_PCR with $TMPFILE" DEBUG "Extending TPM PCR $MODULE_PCR with $MODULE prior of usage"
tpmr extend -ix "$MODULE_PCR" -if $TMPFILE \ tpmr extend -ix "$MODULE_PCR" -if $TMPFILE \
|| die "$MODULE: tpm extend on arguments failed" || die "$MODULE: tpm extend on arguments failed"
fi fi