From 42a014623d5d097a5c21475ad1061fe52320bbdb Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Tue, 23 Apr 2019 16:53:49 -0400 Subject: [PATCH 01/91] - OEM mode is enforced on HOTP/TOTP sealed clean hardware. - OEM is enforced by touching /boot/oem - OEM can be provisioned automatically if /media/oem-provisioning exists which feeds all the secrets automatically. - LUKS rencryption script added, which reencrypts and change Disk Recevory Key passphrase - LibremKey/Nitrokey factory reset script added, which takes user input first and then change key size, generate keys, exports them and flash rom. -Todo: Reset code should be added later on. (To unlock Admin. Else, a DoS is possible on a USB key) - Contains uniformaization of langage. - some shellcheck improved code - LUKS Disk Unlock Key works properly -LVM volumes and disk devices are automatically detected - GPG modules were retouched to remove invalid configure options which generated warnings - LibremKey/Nitrokey is named everywhere for proper credit of partnership for HOTP ... And a lot of other smaller fixes... --- .gitlab-ci.yml | 25 ++ boards/x230/x230.config | 5 +- config/coreboot-x230.config | 2 +- config/linux-x230.config | 4 - initrd/.ash_history | 15 +- .../bin/factory-reset-nitrokey-libremkey.sh | 232 ++++++++++++ initrd/bin/flash-gui.sh | 4 +- initrd/bin/flash.sh | 9 + initrd/bin/gpg-gui.sh | 12 +- initrd/bin/gui-init | 347 ++++++++++++++++-- initrd/bin/kexec-insert-key | 14 +- initrd/bin/kexec-save-default | 271 +++++++++----- initrd/bin/kexec-save-key | 2 +- initrd/bin/kexec-seal-key | 82 +++-- initrd/bin/kexec-select-boot | 13 +- initrd/bin/kexec-sign-config | 46 ++- initrd/bin/kexec-unseal-key | 8 +- initrd/bin/key-init | 10 +- initrd/bin/mount-usb | 11 + initrd/bin/reencrypt-luks | 93 +++++ initrd/bin/seal-libremkey | 33 +- initrd/bin/seal-totp | 2 +- initrd/bin/tpm-reset | 37 +- initrd/bin/unseal-totp | 2 +- initrd/etc/functions | 85 ++++- initrd/init | 12 +- modules/gpg2 | 7 - modules/libassuan | 2 - modules/libgcrypt | 1 - modules/libgpg-error | 1 - modules/libusb | 1 - modules/lvm2 | 2 + modules/npth | 3 - modules/pixman | 2 +- .../generate_diceware-eom-provisioning.sh | 66 ++++ oem-reownership/oem-provisioning.example | 198 ++++++++++ 36 files changed, 1419 insertions(+), 240 deletions(-) create mode 100644 .gitlab-ci.yml create mode 100755 initrd/bin/factory-reset-nitrokey-libremkey.sh create mode 100755 initrd/bin/reencrypt-luks create mode 100755 oem-reownership/generate_diceware-eom-provisioning.sh create mode 100644 oem-reownership/oem-provisioning.example diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 000000000..ac691c8ee --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,25 @@ +image: insurgotech/fedora-29_heads-ci + +stages: + - build + +build: + stage: build + cache: + paths: + - ./ + cache: + untracked: true + paths: + - ./git + script: + - make BOARD=x230-flash + - make BOARD=x230 + - echo "x230-flash hashes:" + - cat ./build/x230-flash/hashes.txt + - echo "x230 hashes:" + - cat ./build/x230/hashes.txt + artifacts: + paths: + - ./build/x230-flash/x230-flash.rom + - ./build/x230/coreboot.rom diff --git a/boards/x230/x230.config b/boards/x230/x230.config index 1d46ba920..0d593e1fc 100644 --- a/boards/x230/x230.config +++ b/boards/x230/x230.config @@ -17,8 +17,11 @@ CONFIG_QRENCODE=y CONFIG_TPMTOTP=y CONFIG_DROPBEAR=y +#CONFIG_SLANG=y +#CONFIG_NEWT=y CONFIG_CAIRO=y CONFIG_FBWHIPTAIL=y +CONFIG_LIBREMKEY=y CONFIG_LINUX_USB=y CONFIG_LINUX_E1000E=y @@ -28,7 +31,7 @@ export CONFIG_BOOTSCRIPT=/bin/gui-init export CONFIG_BOOT_REQ_HASH=n export CONFIG_BOOT_REQ_ROLLBACK=n export CONFIG_BOOT_KERNEL_ADD="intel_iommu=on intel_iommu=igfx_off" -export CONFIG_BOOT_KERNEL_REMOVE="quiet" +export CONFIG_BOOT_KERNEL_REMOVE="" export CONFIG_BOOT_DEV="/dev/sda1" export CONFIG_BOOT_GUI_MENU_NAME="Thinkpad X230 Heads Boot Menu" export CONFIG_USB_BOOT_DEV="/dev/sdb1" diff --git a/config/coreboot-x230.config b/config/coreboot-x230.config index 65b13b581..eab78307a 100644 --- a/config/coreboot-x230.config +++ b/config/coreboot-x230.config @@ -19,6 +19,6 @@ CONFIG_PAYLOAD_LINUX=y CONFIG_PAYLOAD_FILE="../../build/x230/bzImage" CONFIG_PAYLOAD_OPTIONS="" # CONFIG_PXE is not set -CONFIG_LINUX_COMMAND_LINE="intel_iommu=igfx_off quiet" +CONFIG_LINUX_COMMAND_LINE="intel_iommu=igfx_off quiet loglevel=3" CONFIG_LINUX_INITRD="../../build/x230/initrd.cpio.xz" CONFIG_DEBUG_SMM_RELOCATION=y diff --git a/config/linux-x230.config b/config/linux-x230.config index 44bd5ac6b..353670dfb 100644 --- a/config/linux-x230.config +++ b/config/linux-x230.config @@ -56,7 +56,6 @@ CONFIG_KEXEC_FILE=y CONFIG_PHYSICAL_ALIGN=0x1000000 # CONFIG_MODIFY_LDT_SYSCALL is not set # CONFIG_SUSPEND is not set -CONFIG_ACPI_VIDEO=y CONFIG_PCI_MSI=y # CONFIG_HT_IRQ is not set CONFIG_PCI_IOV=y @@ -184,9 +183,7 @@ CONFIG_MFD_SYSCON=y CONFIG_DRM=y CONFIG_DRM_I915=y CONFIG_FB_VESA=y -CONFIG_BACKLIGHT_LCD_SUPPORT=y # CONFIG_LCD_CLASS_DEVICE is not set -CONFIG_BACKLIGHT_CLASS_DEVICE=y # CONFIG_BACKLIGHT_GENERIC is not set CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_USB=y @@ -218,7 +215,6 @@ CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y # CONFIG_PROC_SYSCTL is not set # CONFIG_PROC_PAGE_MONITOR is not set -CONFIG_TMPFS=y # CONFIG_MISC_FILESYSTEMS is not set CONFIG_NLS_DEFAULT="utf8" CONFIG_NLS_CODEPAGE_437=y diff --git a/initrd/.ash_history b/initrd/.ash_history index 996900531..5c292979e 100644 --- a/initrd/.ash_history +++ b/initrd/.ash_history @@ -1,17 +1,22 @@ -#remove invalid kexec_* signed files -mount /dev/sda1 /boot && mount -o remount,rw /boot && rm /boot/kexec* && mount -o remount,ro /boot +#To activate OEM reownership wizard, under Heads recovery console, do: +mount /boot +mount -o remount,rw /boot && echo "oem_name=COMPANY NAME" > /boot/oem && mount -o remount,ro /boot && reboot +#remove invalid kexec.sig signed checksum file +mount /dev/sda1 /boot && mount -o remount,rw /boot && rm /boot/kexec.sig && mount -o remount,ro /boot #Generate keys from GPG smartcard: -mount-usb && gpg --home=/.gnupg/ --card-edit +usb-init && gpg --home=/.gnupg/ --card-edit #Copy generated public key, private_subkey, trustdb and artifacts to external media for backup: -mount -o remount,rw /media && mkdir -p /media/gpg_keys; gpg --export-secret-keys --armor email@address.com > /media/gpg_keys/private.key && gpg --export --armor email@address.com > /media/gpg_keys/public.key && gpg --export-ownertrust > /media/gpg_keys/otrust.txt && cp -r ./.gnupg/* /media/gpg_keys/ 2> /dev/null +mount -o remount,rw /media && mkdir -p /media/gpg_keys; gpg --export-secret-keys --armor email@address.com > /media/gpg_keys/private.key && gpg --export --armor email@address.com > /media/gpg_keys/public.key && cp -r ./.gnupg/* /media/gpg_keys/ 2> /dev/null #Insert public key and trustdb export into reproducible rom: -cbfs -o /media/coreboot.rom -a "heads/initrd/.gnupg/keys/public.key" -f /media/gpg_keys/public.key && cbfs -o /media/coreboot.rom -a "heads/initrd/.gnupg/keys/otrust.txt" -f /media/gpg_keys/otrust.txt +cbfs -o /media/coreboot.rom -a "heads/initrd/.gnupg/keys/public.key" -f /media/gpg_keys/public.key #Flush changes to external media: mount -o,remount ro /media #Flash modified reproducible rom with inserted public key and trustdb export from precedent step. Flushes actual rom's keys (-c: clean): flash.sh -c /media/coreboot.rom #Attest integrity of firmware as it is seal-totp +#Sign a manually verified ISO with your GPG key so you can boot it from Heads +mount-usb && gpg --card-status && gpg --detach-sig /media/some.iso #Verify Intel ME state: cbmem --console | grep '^ME' cbmem --console | less diff --git a/initrd/bin/factory-reset-nitrokey-libremkey.sh b/initrd/bin/factory-reset-nitrokey-libremkey.sh new file mode 100755 index 000000000..6ba00f011 --- /dev/null +++ b/initrd/bin/factory-reset-nitrokey-libremkey.sh @@ -0,0 +1,232 @@ +#!/bin/sh +# +set -e -o pipefail +. /etc/functions +. /tmp/config + +mount_usb(){ +# Mount the USB boot device + if ! grep -q /media /proc/mounts ; then + mount-usb "$CONFIG_USB_BOOT_DEV" || USB_FAILED=1 + if [ $USB_FAILED -ne 0 ]; then + if [ ! -e "$CONFIG_USB_BOOT_DEV" ]; then + whiptail --title 'USB Drive Missing' \ + --msgbox "Insert your USB drive and press Enter to continue." 16 60 USB_FAILED=0 + mount-usb "$CONFIG_USB_BOOT_DEV" || USB_FAILED=1 + fi + if [ $USB_FAILED -ne 0 ]; then + whiptail $CONFIG_ERROR_BG_COLOR --title 'ERROR: Mounting /media Failed' \ + --msgbox "Unable to mount $CONFIG_USB_BOOT_DEV" 16 60 + fi + fi + fi +} + +if (whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'Factory Reset and reownership of GPG card' \ + --yesno "You are about to factory reset your GPG card!\n\nThis will:\n 1-Wipe all PRIVATE keys that were previously kept inside GPG card\n 2-Set default key size to 4096 bits (maximum)\n 3-Ask you to choose two passwords to interact with the card:\n 3.1: An administrative passphrase used to manage the card\n 3.2: A user passphrase (PIN) used everytime you sign\n encrypt/decrypt content\n4-Generate new Encryption, Signing and Authentication keys\n inside your GPG card\n5-Export associated public key, replace the one being\n present and trusted inside running BIOS, and reflash\n the SPI flash with resulting rom image.\n\nAs a result, the running BIOS will be modified. Would you like to continue?" 30 90) then + + whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'WARNING: Please Insert A USB Disk' --msgbox \ + "Please insert a USB disk on which you want to store your GPG public key\n and trustdb.\n\nThose will be backuped under the 'gpg_keys' directory.\n\nHit Enter to continue." 30 90 + + mount_usb || die "Unable to mount USB device." + #Copy generated public key, private_subkey, trustdb and artifacts to external media for backup: + mount -o remount,rw /media || die "Unable to remount /media into Read Write mode. Is the device write protected?" + + #TODO: Circumvent permission bug with mkdir and chmod permitting to use gpg --home=/media/gpg_keys directly. + #Cannot create a new gpg homedir with right permissions nor chmod 700 that directory. + #Meanwhile, we reuse /.gnupg by temporarely deleting it's existing content. + rm -rf .gnupg/* 2> /dev/null || true 2> /dev/null + killall gpg-agent gpg scdaemon 2> /dev/null || true 2> /dev/null + + if [ -z "$oem_gpg_Admin_PIN" ] || [ -z "$oem_gpg_User_PIN" ]; then + #Setting new passwords + gpgcard_user_pass1=1 + gpgcard_user_pass2=2 + gpgcard_admin_pass1=3 + gpgcard_admin_pass2=4 + else + gpgcard_user_pass1=$(echo -n "$oem_gpg_User_PIN") + gpgcard_user_pass2=$(echo -n "$oem_gpg_User_PIN") + gpgcard_admin_pass1=$(echo -n "$oem_gpg_Admin_PIN") + gpgcard_admin_pass2=$(echo -n "$oem_gpg_Admin_PIN") + fi + + while [[ "$gpgcard_user_pass1" != "$gpgcard_user_pass2" ]] || [[ ${#gpgcard_user_pass1} -lt 6 || ${#gpgcard_user_pass1} -gt 20 ]];do + { + echo -e "\nChoose your new GPG card user password (PIN) that will be typed when using GPG smartcard (Sign files, encrypt emails and files).\nIt needs to be a least 6 but not more then 20 characters:" + read -s gpgcard_user_pass1 + echo -e "\nRetype user passphrase:" + read -s gpgcard_user_pass2 + if [[ "$gpgcard_user_pass1" != "$gpgcard_user_pass2" ]]; then echo "Passwords typed were different."; fi + };done + gpgcard_user_pass=$gpgcard_user_pass1 + + while [[ "$gpgcard_admin_pass1" != "$gpgcard_admin_pass2" ]] || [[ ${#gpgcard_admin_pass1} -lt 8 || ${#gpgcard_admin_pass1} -gt 20 ]] || [ "$gpgcard_admin_pass1" != "${gpgcard_admin_pass1% *}" ]; do + { + echo -e "\nChoose your new GPG card admin password that will be typed when managing GPG smartcard (HOTP sealing, managing key, etc).\nIt needs to be a least 8 but not more then 20 characters WHILE NOT CONTAINING SPACES:" + read -s gpgcard_admin_pass1 + echo -e "\nRetype admin password:" + read -s gpgcard_admin_pass2 + + if [[ "$gpgcard_admin_pass1" != "$gpgcard_admin_pass2" ]] || [ "$gpgcard_admin_pass1" != "${gpgcard_admin_pass1% *}" ]; then echo "Passwords typed were different or contained spaces."; fi + };done + gpgcard_admin_pass=$gpgcard_admin_pass1 + + echo -e "\n\n" + echo -e "We will generate a GnuPG (GPG) keypair identifiable with the following text form:" + echo -e "Real Name (Comment) email@address.org" + + gpgcard_real_name=$(echo -n "$oem_gpg_real_name") + while [[ ${#gpgcard_real_name} -lt 5 ]]; do + { + echo -e "\nEnter your Real Name (At least 5 characters long):" + read -r gpgcard_real_name + };done + + gpgcard_email_address=$(echo -n "$oem_gpg_email") + while ! $(expr "$gpgcard_email_address" : '.*@' >/dev/null); do + { + echo -e "\nEnter your email@adress.org:" + read -r gpgcard_email_address + };done + + gpgcard_comment=$(echo -n "$oem_gpg_comment") + while [[ ${#gpgcard_comment} -gt 60 ]] || [[ -z "$gpgcard_comment" ]]; do + { + echo -e "\nEnter Comment (To distinguish this key from others with same previous attributes. Must be smaller then 60 characters):" + read -r gpgcard_comment + };done + + #Copy generated public key, private_subkey, trustdb and artifacts to external media for backup: + mount -o remount,rw /media || die "Unable to remount /media into Read Write mode. Is the device write protected?" + + #backup existing /media/gpg_keys directory + if [ -d /media/gpg_keys ];then + newdir="/media/gpg_keys-$(date '+%Y-%m-%d-%H_%M_%S')" + echo "Backing up /media/gpg_keys into $newdir" + mv /media/gpg_keys "$newdir" || die "Moving old gpg_keys directory into $newdir failed." + fi + + mkdir -p /media/gpg_keys + + #Generate Encryption, Signing and Authentication keys + whiptail --clear --title 'GPG card key generation' --msgbox \ + "BE PATIENT! Generating 4096 bits Encryption, Signing and Authentication\n keys take around 5 minutes each! Be prepared to patient around 15 minutes!\n\nHit Enter to continue" 30 90 + + confirm_gpg_card + + #Factory reset GPG card + { + echo admin + echo factory-reset + echo y + echo yes + } | gpg --command-fd=0 --status-fd=1 --pinentry-mode=loopback --card-edit --home=/.gnupg/ || die "Factory resetting the GPG card failed." + + #Setting new admin and user passwords in GPG card + { + echo admin + echo passwd + echo 1 + echo 123456 #Default user password after factory reset of card + echo "$gpgcard_user_pass" + echo "$gpgcard_user_pass" + echo 3 + echo 12345678 #Default administrator password after factory reset of card + echo "$gpgcard_admin_pass" + echo "$gpgcard_admin_pass" + echo Q + } | gpg --command-fd=0 --status-fd=2 --pinentry-mode=loopback --card-edit --home=/.gnupg/ || die "Setting new admin and user PINs in GPG card failed." + + #Set GPG card key attributes key sizes to 4096 bits + { + echo admin + echo key-attr + echo 1 # RSA + echo 4096 #Signing key size set to maximum supported by SmartCard + echo "$gpgcard_admin_pass" + echo 1 # RSA + echo 4096 #Encryption key size set to maximum supported by SmartCard + echo "$gpgcard_admin_pass" + echo 1 # RSA + echo 4096 #Authentication key size set to maximum supported by SmartCard + echo "$gpgcard_admin_pass" + } | gpg --command-fd=0 --status-fd=2 --pinentry-mode=loopback --card-edit --home=/.gnupg/ || die "Setting key attributed to RSA 4096 bits in GPG card failed." + + { + echo admin + echo generate + echo n + echo "$gpgcard_admin_pass" + echo "$gpgcard_user_pass" + echo 1y + echo "$gpgcard_real_name" + echo "$gpgcard_email_address" + echo "$gpgcard_comment" + } | gpg --command-fd=0 --status-fd=2 --pinentry-mode=loopback --card-edit --home=/.gnupg/ || die "Setting real name, e-mail address and comment in GPG failed." + + #Export and inject public key and trustdb export into extracted rom with current user keys being wiped + rom=/tmp/gpg-gui.rom + #remove invalid signsignature file + mount -o remount,rw /boot + rm -f /boot/kexec.sig + mount -o remount,ro /boot + + gpg --home=/.gnupg/ --export --armor "$gpgcard_email_address" > /media/gpg_keys/public.key || die "Exporting public key to /media/gpg_keys/public.key failed." + cp -rf /.gnupg/openpgp-revocs.d/* /media/gpg_keys/ 2> /dev/null || die "Copying revocation certificated into /media/gpg_keys/ failed." + cp -rf /.gnupg/private-keys-v1.d/* /media/gpg_keys/ 2> /dev/null || die "Copying secring exported keys to /media/gpg_keys/ failed." + cp -rf /.gnupg/pubring.* /.gnupg/trustdb.gpg /media/gpg_keys/ 2> /dev/null || die "Copying public keyring into /media/gpg_keys/ failed." + + #Flush changes to external media + mount -o remount,ro /media + + #Read rom + /bin/flash.sh -r $rom || die "Flashing back $rom including your newly genereated and exported public key failed." + + #delete previously injected public.key + if (cbfs -o $rom -l | grep -q "heads/initrd/.gnupg/keys/public.key"); then + cbfs -o $rom -d "heads/initrd/.gnupg/keys/public.key" || die "Deleting old public key from running rom backup failed." + fi + + #delete previously injected GPG1 and GPG2 pubrings + if (cbfs -o $rom -l | grep -q "heads/initrd/.gnupg/pubring.kbx"); then + cbfs -o $rom -d "heads/initrd/.gnupg/pubring.kbx" || die "Deleting old public keyring from running rom backup failed." + if (cbfs -o $rom -l | grep -q "heads/initrd/.gnupg/pubring.gpg"); then + cbfs -o $rom -d "heads/initrd/.gnupg/pubring.gpg" || die "Deleting old and deprecated public keyring from running rom backup failed." + if [ -e /.gnupg/pubring.gpg ];then + rm /.gnupg/pubring.gpg + fi + fi + fi + #delete previously injected trustdb + if (cbfs -o $rom -l | grep -q "heads/initrd/.gnupg/trustdb.gpg") then + cbfs -o $rom -d "heads/initrd/.gnupg/trustdb.gpg" || die "Deleting old trust database from running rom backup failed." + fi + #Remove old method of exporting/importing owner trust exported file + if (cbfs -o $rom -l | grep -q "heads/initrd/.gnupg/otrust.txt") then + cbfs -o $rom -d "heads/initrd/.gnupg/otrust.txt" || die "Deleting old and depracated trust database export failed." + fi + + #Insert public key in armored form and trustdb ultimately trusting user's key into reproducible rom: + cbfs -o "$rom" -a "heads/initrd/.gnupg/pubring.kbx" -f /.gnupg/pubring.kbx || die "Inserting public keyring in runnning rom backup failed." + cbfs -o "$rom" -a "heads/initrd/.gnupg/trustdb.gpg" -f /.gnupg/trustdb.gpg || die "Inserting trust databse in running rom backup failed." + + if (whiptail --title 'Flash ROM?' \ + --yesno "This will replace your old ROM with $rom\n\nDo you want to proceed?" 16 90) then + /bin/flash.sh $rom + whiptail --title 'ROM Flashed Successfully' \ + --msgbox "New $rom flashed successfully.\n\nIf your keys have changed, be sure to re-sign all files in /boot\nafter you reboot.\n\nPress Enter to continue" 16 60 + if [ -s /boot/oem ];then + mount -o remount,rw /boot + echo "gpg_factory_resetted" >> /boot/oem + mount -o remount,ro /boot + fi + mount -o remount,ro /media + else + exit 0 + fi + + whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'WARNING: Reboot required' --msgbox \ + "A reboot is required.\n\n Your firmware has been reflashed with your own public key and trust\n database included.\n\n Heads will detect the firmware change and react accordingly:\n It will ask you to reseal TOTP/HOTP (seal BIOS integrity),\n take /boot integrity measures and sign them with your freshly\n factory resetted GPG card and it's associated user password (PIN).\n\nHit Enter to reboot." 30 90 + /bin/reboot +fi diff --git a/initrd/bin/flash-gui.sh b/initrd/bin/flash-gui.sh index 3780051a1..22621e644 100755 --- a/initrd/bin/flash-gui.sh +++ b/initrd/bin/flash-gui.sh @@ -86,7 +86,7 @@ while true; do f|c ) if (whiptail --title 'Flash the BIOS with a new ROM' \ --yesno "This requires you insert a USB drive containing:\n* Your BIOS image (*.rom)\n\nAfter you select this file, this program will reflash your BIOS\n\nDo you want to proceed?" 16 90) then - mount_usb + mount_usb || die "Unable to mount USB device." if grep -q /media /proc/mounts ; then find /media -name '*.rom' > /tmp/filelist.txt file_selector "/tmp/filelist.txt" "Choose the ROM to flash" @@ -104,7 +104,7 @@ while true; do /bin/flash.sh "$ROM" fi whiptail --title 'ROM Flashed Successfully' \ - --msgbox "$ROM flashed successfully.\nPress Enter to reboot" 16 60 + --msgbox "$ROM flashed successfully. Press Enter to reboot" 16 60 umount /media /bin/reboot else diff --git a/initrd/bin/flash.sh b/initrd/bin/flash.sh index e89c9a98c..6b7ad02d2 100755 --- a/initrd/bin/flash.sh +++ b/initrd/bin/flash.sh @@ -46,6 +46,15 @@ flash_rom() { flashrom $FLASHROM_OPTIONS -w /tmp/${CONFIG_BOARD}.rom \ || die "$ROM: Flash failed" + + if [ -e /boot/kexec_key_devices.txt ] || [ -e /boot/kexec_key_lvm.txt ]; then + echo -e "\n\nBoth your TOTP/HOTP codes and TPM released Disk Unlock Key were invalidated since measured boot integrity changed." + echo -e "You will be requested to reseal TOTP/HOTP secrets, to set a new default boot option and define a new Disk Unlock Key passphrase.\n\n" + mount_boot + mount -o remount,rw /boot + touch /boot/reset_disk_unlock_key + mount -o remount,ro /boot + fi fi } diff --git a/initrd/bin/gpg-gui.sh b/initrd/bin/gpg-gui.sh index f75661075..646ffa8c9 100755 --- a/initrd/bin/gpg-gui.sh +++ b/initrd/bin/gpg-gui.sh @@ -76,6 +76,7 @@ while true; do 'a' ' Add GPG key to standalone BIOS image + flash' \ 'l' ' List GPG keys in your keyring' \ 'g' ' Generate GPG keys on a USB security token' \ + 'F' ' Factory Reset Nitrokey Pro v2/LibremKey GPG Card' \ 'x' ' Exit' \ 2>/tmp/whiptail || recovery "GUI menu failed" @@ -88,7 +89,7 @@ while true; do "a" ) if (whiptail --title 'ROM and GPG public key required' \ --yesno "This requires you insert a USB drive containing:\n* Your GPG public key (*.key or *.asc)\n* Your BIOS image (*.rom)\n\nAfter you select these files, this program will reflash your BIOS\n\nDo you want to proceed?" 16 90) then - mount_usb + mount_usb || die "Unable to mount USB device" if grep -q /media /proc/mounts ; then find /media -name '*.key' > /tmp/filelist.txt find /media -name '*.asc' >> /tmp/filelist.txt @@ -159,8 +160,8 @@ while true; do ;; "r" ) if (whiptail --title 'GPG public key required' \ - --yesno "This requires you insert a USB drive containing:\n* Your GPG public key (*.key or *.asc)\n\nAfter you select this file, this program will copy and reflash your BIOS\n\nDo you want to proceed?" 16 90) then - mount_usb + --yesno "This requires you insert a USB drive containing:\n* Your GPG public key (*.key or *.asc)\n\nNormally, the file should be named public.key\n\nAfter you select this file, this program will copy and reflash your BIOS\n\nDo you want to proceed?" 16 90) then + mount_usb || die "Unable to mount USB device" if grep -q /media /proc/mounts ; then find /media -name '*.key' > /tmp/filelist.txt find /media -name '*.asc' >> /tmp/filelist.txt @@ -238,7 +239,10 @@ while true; do echo "********************************************************************************" gpg --card-edit ;; + "F" ) + /bin/factory-reset-nitrokey-libremkey.sh + ;; esac done -exit 0 +exit 0 diff --git a/initrd/bin/gui-init b/initrd/bin/gui-init index 7a07bbea8..46863a084 100755 --- a/initrd/bin/gui-init +++ b/initrd/bin/gui-init @@ -6,12 +6,49 @@ CONFIG_BOOT_GUI_MENU_NAME='Heads Boot Menu' . /etc/functions . /tmp/config -mount_boot() -{ - # Mount local disk if it is not already mounted - if ! grep -q /boot /proc/mounts ; then - mount -o ro /boot \ - || recovery "Unable to mount /boot" +file_selector() { + FILE="" + FILE_LIST=$1 + MENU_MSG=${2:-"Choose the file"} + # create file menu options + 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" + whiptail --clear --title "Select your File" \ + --menu "${MENU_MSG} [1-$n, a to abort]:" 20 120 8 \ + -- $MENU_OPTIONS \ + 2>/tmp/whiptail || die "Aborting" + + option_index=$(cat /tmp/whiptail) + + if [ "$option_index" = "a" ]; then + option="a" + return + fi + + option=$(head -n "$option_index" "$FILE_LIST" | tail -1) + if [ "$option" == "a" ]; then + return + fi + done + if [ -n "$option" ]; then + FILE=$option + fi + else + whiptail $CONFIG_ERROR_BG_COLOR --title 'ERROR: No Files Found' \ + --msgbox "No Files found matching the pattern. Aborting." 16 60 + exit 1 fi } verify_global_hashes() @@ -62,11 +99,11 @@ verify_global_hashes() update_checksums() { if (whiptail --title 'Update Checksums and sign all files in /boot' \ - --yesno "You have chosen to update the checksums and sign all of the files in /boot.\n\nThis means that you trust that the files in /boot have not been tampered with.\n\nYou will need your GPG key to continue and this change will modify your disk.\n\nDo you want to continue?" 16 90) then + --yesno "You have chosen to update the checksums and sign all of the files in /boot.\n\nThis means that you trust that the files in /boot have not been tampered\n with.\n\nYou will need your GPG key to continue and this change will modify your\n disk.\n\nDo you want to continue?" 16 90) then mount_boot mount -o rw,remount /boot - cd /boot + cd /boot || die "Not able to change directory to /boot." find ./ -type f ! -name '*kexec*' | xargs sha256sum > /boot/kexec_hashes.txt DEFAULT_FILES=$(cat /boot/kexec_default_hashes.txt | cut -f3 -d ' ') echo $DEFAULT_FILES | xargs sha256sum > /boot/kexec_default_hashes.txt @@ -92,17 +129,243 @@ update_checksums() update_totp() { echo "Scan the QR code to add the new TOTP secret" - /bin/seal-totp + /bin/seal-totp $CONFIG_BOARD if [ -x /bin/libremkey_hotp_verification ]; then - echo "Once you have scanned the QR code, hit Enter to configure your Librem Key" + echo "Once you have scanned the QR code, hit Enter to configure your LibremKey/Nitrokey" read /bin/seal-libremkey + while [ $? -ne 0 ];do + echo -e "\n\nSealing HOTP secret into LibremKey/Nitrokey failed. Let's try again by resealing both TOTP and HOTP." + update_totp + /bin/seal-libremkey + done else echo "Once you have scanned the QR code, hit Enter to reboot" read fi /bin/reboot } +read_oem_file() +{ + echo "Mounting USB drive to provision OEM reownership from /media/oem-provisioning..." + /bin/mount-usb || warn "Unable to mount USB device. Continuing" + if [ -e /media/oem-provisioning ]; then + oem_gpg_Admin_PIN=$(grep "oem_gpg_Admin_PIN" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_gpg_Admin_PIN" ]; then + export oem_gpg_Admin_PIN="$oem_gpg_Admin_PIN" + else + unset oem_gpg_Admin_PIN + fi + + oem_gpg_User_PIN=$(grep "oem_gpg_User_PIN" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_gpg_User_PIN" ]; then + export oem_gpg_User_PIN="$oem_gpg_User_PIN" + else + unset oem_gpg_User_PIN + fi + + oem_gpg_real_name=$(grep "oem_gpg_real_name" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_gpg_real_name" ]; then + export oem_gpg_real_name="$oem_gpg_real_name" + else + unset oem_gpg_real_name + fi + + oem_gpg_email=$(grep "oem_gpg_email" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_gpg_email" ]; then + export oem_gpg_email="$oem_gpg_email" + else + unset oem_gpg_email + fi + + oem_gpg_comment=$(grep "oem_gpg_comment" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_gpg_comment" ]; then + export oem_gpg_comment="$oem_gpg_comment" + else + unset oem_gpg_comment + fi + + oem_luks_actual_Disk_Recovery_Key=$(grep "oem_luks_actual_Disk_Recovery_Key" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_luks_actual_Disk_Recovery_Key" ]; then + export oem_luks_actual_Disk_Recovery_Key="$oem_luks_actual_Disk_Recovery_Key" + else + unset oem_luks_actual_Disk_Recovery_Key + fi + + oem_luks_new_Disk_Recovery_Key=$(grep "oem_luks_new_Disk_Recovery_Key" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_luks_new_Disk_Recovery_Key" ]; then + export oem_luks_new_Disk_Recovery_Key="$oem_luks_new_Disk_Recovery_Key" + else + unset oem_luks_new_Disk_Recovery_Key + fi + + oem_luks_Disk_Unlock_Key=$(grep "oem_luks_Disk_Unlock_Key" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_luks_Disk_Unlock_Key" ]; then + export oem_luks_Disk_Unlock_Key="$oem_luks_Disk_Unlock_Key" + else + unset oem_luks_Disk_Unlock_Key + fi + + oem_TPM_Owner_Password=$(grep "oem_TPM_Owner_Password" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_TPM_Owner_Password" ]; then + export oem_TPM_Owner_Password="$oem_TPM_Owner_Password" + else + unset oem_TPM_Owner_Password + fi + + export oem_configuration_read=1 + fi +} +check_onboarding_progress() +{ + mount_boot + if [ -e /boot/oem ]; then + res=$(grep onboarding /boot/oem 2>&1 > /dev/null) + if [ $? -ne 0 ];then + #Show Onboarding menu once. + whiptail --title 'Hardware reownership Wizard' --msgbox \ + "The received hardware is currently owned by $oem_name.\nWe will change that.\n\nThis Wizard will otherwise make you own your own hardware by:\n1-Reencrypting encrypted drive content (LUKS container)\n2-Changing LUKS Disk Recovery Key and it's passphrase\n3-Resetting your LibremKey/Nitrokey Pro v2 to factory defaults\n4-Setting User and Admin PINs into your LibremKey/NitroKey\n4-Generating keys in it, exporting public key and\n importing it in the rom prior to reprogramming the SPI flash with it\n6-Taking integrity measures of all /boot files and sign the resulting\n checksum file with yourLibremKey/Nitrokey Pro\n6-Owning your Trusted Platform Module (TPM)\n\nScan the QR Code with an OTP app only after Reset the TPM last phase.\n\nHit Enter to continue." 20 20 + whiptail --title 'Hardware reownership Wizard' --msgbox \ + "On the next screen, MAKE SURE THAT THE HOTP CODE IS: 'Success'\n\nIf it's not, reboot your hardware with your Librem/Nitrokey inserted.\n\nIf the HOTP code is still invalid, your hardware may been tampered with in\ntransit. Contact $oem_name." 20 20 + totp_confirm="O" + echo $totp_confirm > /tmp/whiptail + mount -o remount,rw /boot + echo "onboarding" >> /boot/oem + mount -o remount,ro /boot + fi + res=$(grep luks_reencrypted /boot/oem 2>&1 > /dev/null) + if [ $? -ne 0 ];then + export reownership_state="luks_reencryption" + totp_confirm="R" + echo $totp_confirm > /tmp/whiptail + return + fi + res=$(grep luks_passwd_changed /boot/oem 2>&1 > /dev/null) + if [ $? -ne 0 ];then + export reownership_state="luks_password_change" + totp_confirm="R" + return + fi + res=$(grep gpg_factory_resetted /boot/oem 2>&1 > /dev/null) + if [ $? -ne 0 ];then + /bin/factory-reset-nitrokey-libremkey.sh + return + fi + res=$(grep tpm_reowned /boot/oem 2>&1 > /dev/null) + if [ $? -ne 0 ];then + totp_confirm="p" + echo $totp_confirm > /tmp/whiptail + return + fi + if [ $(grep -E "luks_reencrypted|luks_passwd_changed|gpg_factory_resetted|tpm_reowned" /boot/oem | uniq | wc -l) -eq 4 ];then + if [ $HOTP = "Success" ];then + mount -o remount,rw /boot + rm /boot/oem + mount -o remount,ro /boot + unset totp_confirm + unset reownership_state + whiptail --title 'DISK UNLOCK KEY ADVICE 1/3' --msgbox \ + "***You SHOULD SET a new Disk Unlock Key for your own data privacy!!!***\n\nDoing so, a witness will only be able to type observed Disk Unlock\n Key passphrase from this computer and won't be able on a cloned\n copy of this disk.\n\nThe release of Disk Unlock Key happens ONLY if TPM attests firmware\nintegrity, and only if Disk Unlock Key passphrase is valid.\n\nPlease hit Enter to continue" 30 60 + + whiptail --title 'DISK UNLOCK KEY ADVICE 2/3' --msgbox \ + "Otherwise, typing your Disk Recovery Key passphrase at boot puts you\nat risk. Someone could clone your disk and type that witnessed\npassphrase and access your data both locally and from a cloned\ndisk.\n\nCoupled with a strong passphrase, this improves your data privacy.\nCONSIDER YOURSELF WARNED.\n\nPlease hit Enter to continue" 30 60 + + whiptail --title 'DISK UNLOCK KEY ADVICE 3/3' --msgbox \ + "To set Disk Unlock Key, released by the TPM only if firmware integrity\n is attested:\n\nSelect from Main menu:\n\nAdvanced Options menu -> Other Boot Options -> Show OS boot menu\n1-Then select the first boot option proposed (dynamic option)\n2-Then,answer Y when asked to add Disk Unlock Key to the TPM.\n\nYou will be prompted to set one in the following steps.\n\nPlease hit Enter to continue" 30 60 + return + else + #Deal with corner case where after inserting key in previous step, HOTP seal fails with provided good password. + #In that case, we regenerate HOTP and TOTP + totp_confirm="g" + echo $totp_confirm > /tmp/whiptail + fi + fi + else + reset_disk_unlock_key + return + fi +} +reset_disk_unlock_key() +{ + mount_boot + + if [ "$CONFIG_TPM" = n ]; then + TOTP="NO TPM" + else + TOTP=`unseal-totp` + if [ $? -ne 0 ]; then + echo "Error generating TOTP code. We will regenerate it now." + update_totp + continue + elif [ -x /bin/libremkey_hotp_verification ]; then + HOTP=`unseal-hotp` + enable_usb + if ! libremkey_hotp_verification info ; then + whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'WARNING: Please Insert Your LibremKey/Nitrokey' --msgbox "Your LibremKey/Nitrokey was not detected.\n\nPlease insert your LibremKey/Nitrokey" 30 90 + fi + # Don't output HOTP codes to screen, so as to make replay attacks harder + libremkey_hotp_verification check "$HOTP" + case "$?" in + 0 ) + HOTP="Success" + ;; + 4 ) + HOTP="Invalid code" + MAIN_MENU_BG_COLOR=$CONFIG_ERROR_BG_COLOR + ;; + * ) + HOTP="Error checking code, Insert LibremKey/Nitrokey and retry" + MAIN_MENU_BG_COLOR=$CONFIG_WARNING_BG_COLOR + ;; + esac + else + HOTP='N/A' + fi + + if [ $HOTP = "Success" ];then + mount -o remount,rw /boot + rm /boot/reset_disk_unlock_key + mount -o remount,ro /boot + verify_global_hashes + kexec-select-boot -m -b /boot -c "grub.cfg" -g + continue + else + echo -e "HOTP status: $HOTP\n\nHit Enter to regenerate new TOTP/HOTP codes." + read + update_totp + fi + continue + fi +} + +mount_boot +if [ -e /boot/oem ];then + if [ -z "$oem_configuration_read" ]; then + #Read /media/oem-provisioning file once to read provisioned secrets + read_oem_file + + oem_name=$(grep "oem_name" /boot/oem | awk -F '=' {'print $2'}) + if [ -n "$oem_name" ]; then + export oem_name="$oem_name" + else + oem_name="your OEM" + export oem_name="$oem_name" + fi + fi +fi + + +#TODO:validate that resetting disk unlock key only happens when /boot/oem doesn't exist anymore. Should happen after TPM reset. +#Flashing modifies measurements, which should trigger TOTP/HOTP resealing. That happens when inserting gpg public key. +#Measurements become invalid when TPM is reset, also. +if [ -e /boot/reset_disk_unlock_key ] && [ ! -e /boot/oem ]; then + if (whiptail $CONFIG_WARNING_BG_COLOR --title "WARNING: You must change your Disk Unlock Key" \ + --yesno "You just updated the ROM, which requires resealing TOTP/HOTP secrets.\nTPM released Disk Unlock Key stored in LUKS header must also be regenerated.\n\nIf you did not modify the ROM, this might be a sign of system compromise.\nIn that case, you should say No here and investigate." 30 90) then + reset_disk_unlock_key + else + recovery "User refused to update TOTP/HOTP following what seemed to be a ROM update. Time to investigate changes manually." + fi +fi last_half=X while true; do @@ -121,6 +384,7 @@ while true; do totp_confirm=$(cat /tmp/whiptail) fi + if [ "$totp_confirm" = "i" -o -z "$totp_confirm" ]; then # update the TOTP code every thirty seconds date=`date "+%Y-%m-%d %H:%M:%S"` @@ -132,13 +396,14 @@ while true; do last_half=$half; TOTP=`unseal-totp` if [ $? -ne 0 ]; then + #Normal path. We give user a choice. whiptail $CONFIG_ERROR_BG_COLOR --clear --title "ERROR: TOTP Generation Failed!" \ --menu "ERROR: Heads couldn't generate the TOTP code.\n\nIf this is the first time the system has booted, you should reset the TPM\nand set your own password\n\nIf you just reflashed your BIOS, you'll need to generate a new TOTP secret.\n\nIf you have not just reflashed your BIOS, THIS COULD INDICATE TAMPERING!\n\nHow would you like to proceed?" 30 90 4 \ 'g' ' Generate new TOTP/HOTP secret' \ 'i' ' Ignore error and continue to default boot menu' \ 'p' ' Reset the TPM' \ 'x' ' Exit to recovery shell' \ - 2>/tmp/whiptail || recovery "GUI menu failed" + 2>/tmp/whiptail || recovery "GUI menu failed" totp_confirm=$(cat /tmp/whiptail) fi @@ -150,10 +415,10 @@ while true; do HOTP=`unseal-hotp` enable_usb if ! libremkey_hotp_verification info ; then - whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'WARNING: Please Insert Your Librem Key' --msgbox "Your Librem Key was not detected.\n\nPlease insert your Librem Key" 30 90 + whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'WARNING: Please Insert Your LibremKey/Nitrokey' --msgbox "Your LibremKey/Nitrokey was not detected.\n\nPlease insert your LibremKey/Nitrokey" 30 90 fi # Don't output HOTP codes to screen, so as to make replay attacks harder - libremkey_hotp_verification check $HOTP + libremkey_hotp_verification check "$HOTP" case "$?" in 0 ) HOTP="Success" @@ -163,7 +428,7 @@ while true; do MAIN_MENU_BG_COLOR=$CONFIG_ERROR_BG_COLOR ;; * ) - HOTP="Error checking code, Insert Librem Key and retry" + HOTP="Error checking code, Insert LibremKey/Nitrokey and retry" MAIN_MENU_BG_COLOR=$CONFIG_WARNING_BG_COLOR ;; esac @@ -171,14 +436,32 @@ while true; do HOTP='N/A' fi - whiptail $MAIN_MENU_BG_COLOR --clear --title "$CONFIG_BOOT_GUI_MENU_NAME" \ - --menu "$date\nTOTP: $TOTP | HOTP: $HOTP" 20 90 10 \ - 'y' ' Default boot' \ - 'a' ' Advanced Settings -->' \ - 'x' ' Exit to recovery shell' \ - 2>/tmp/whiptail || recovery "GUI menu failed" + if [ -e /boot/oem ]; then + check_onboarding_progress + totp_confirm="O" + echo $totp_confirm > /tmp/whiptail + else + whiptail $MAIN_MENU_BG_COLOR --clear --title "$CONFIG_BOOT_GUI_MENU_NAME" \ + --menu "Greenwich Mean Time (GMT) : $date\nTOTP: $TOTP | HOTP: $HOTP" 20 90 10 \ + 'y' ' Default boot' \ + 'a' ' Advanced Settings -->' \ + 'x' ' Exit to recovery shell' \ + 2>/tmp/whiptail || recovery "GUI menu failed" + totp_confirm=$(cat /tmp/whiptail) + fi + fi - totp_confirm=$(cat /tmp/whiptail) + if [ "$totp_confirm" = "O" ]; then + whiptail $MAIN_MENU_BG_COLOR --clear --title "$CONFIG_BOOT_GUI_MENU_NAME: Reownership" \ + --menu "Greenwich Mean Time (GMT) : $date\nTOTP: $TOTP | HOTP: $HOTP" 20 90 10 \ + 'C' ' Continue ownership of devices' \ + 'x' ' Exit to recovery shell' \ + 2>/tmp/whiptail || recovery "GUI menu failed" + totp_confirm=$(cat /tmp/whiptail) + fi + + if [ "$totp_confirm" = "C" ]; then + check_onboarding_progress fi if [ "$totp_confirm" = "a" ]; then @@ -186,10 +469,11 @@ while true; do --menu "Configure Advanced Settings" 20 90 10 \ 'o' ' Other Boot Options -->' \ 't' ' TPM/TOTP/HOTP Options -->' \ - 's' ' Update checksums and sign all files in /boot' \ - 'c' ' Change configuration settings -->' \ - 'f' ' Flash/Update the BIOS -->' \ 'G' ' GPG Options -->' \ + 'f' ' Flash/Update the BIOS -->' \ + 'c' ' Change configuration settings -->' \ + 's' ' Update checksums and sign all files in /boot' \ + 'R' ' Reencrypt LUKS container' \ 'r' ' <-- Return to main menu' \ 2>/tmp/whiptail || recovery "GUI menu failed" @@ -260,8 +544,16 @@ while true; do if [ "$totp_confirm" = "p" ]; then if (whiptail --title 'Reset the TPM' \ - --yesno "This will clear the TPM and TPM password, replace them with new ones!\n\nDo you want to proceed?" 16 90) then + --yesno "This will clear the TPM content and reset TPM Owner password.\n\nDo you want to proceed?" 16 90) then /bin/tpm-reset + + #set flag in oem file + mount_boot + if [ -s /boot/oem ];then + mount -o remount,rw /boot + echo "tpm_reowned" >> /boot/oem + mount -o remount,ro /boot + fi # now that the TPM is reset, remove invalid TPM counter files mount_boot @@ -330,6 +622,11 @@ while true; do continue fi + if [ "$totp_confirm" = "R" ]; then + /bin/reencrypt-luks + continue + fi + if [ "$totp_confirm" = "y" -o -n "$totp_confirm" ]; then # Try to boot the default mount_boot diff --git a/initrd/bin/kexec-insert-key b/initrd/bin/kexec-insert-key index 5b4020ecd..dde229d40 100755 --- a/initrd/bin/kexec-insert-key +++ b/initrd/bin/kexec-insert-key @@ -1,5 +1,5 @@ #!/bin/sh -# Unseal a disk key from TPM and add to a new initramfs +# Unseal a Disk Unlock Key from TPM and add to a new initramfs set -e -o pipefail . /etc/functions @@ -23,10 +23,10 @@ if [ -r "$TMP_KEY_LVM" ]; then die "No LVM volume group defined for activation" fi lvm vgchange -a y $VOLUME_GROUP \ - || die "$VOLUME_GROUP: unable to activate volume group" + || die "$VOLUME_GROUP: Unable to activate volume group" fi -# Measure the LUKS headers before we unseal the disk key +# Measure the LUKS headers before we unseal the Disk Unock Key cat "$TMP_KEY_DEVICES" | cut -d\ -f1 | xargs /bin/qubes-measure-luks \ || die "LUKS measure failed" @@ -37,12 +37,12 @@ INITRD_DIR=/tmp/secret/initrd SECRET_CPIO=/tmp/secret/initrd.cpio mkdir -p "$INITRD_DIR/etc" -# Attempt to unseal the disk key from the TPM +# Attempt to unseal the Disk Unlock Key from the TPM # should we give this some number of tries? unseal_failed="n" if ! kexec-unseal-key "$INITRD_DIR/secret.key" ; then unseal_failed="y" - echo "!!! Failed to unseal the TPM LUKS disk key" + echo "!!! Failed to unseal the TPM LUKS Disk Unlock Key" fi # Override PCR 4 so that user can't read the key @@ -54,14 +54,14 @@ if [ "$unseal_failed" = "y" ]; then confirm_boot="n" read \ -n 1 \ - -p "Do you wish to boot and use the disk recovery key? [Y/n] " \ + -p "Do you wish to boot and use the Disk Recovery Key? [Y/n] " \ confirm_boot if [ "$confirm_boot" != 'y' \ -a "$confirm_boot" != 'Y' \ -a -n "$confirm_boot" ] \ ; then - die "!!! Aborting boot due to failure to unseal TPM disk key" + die "!!! Aborting boot due to failure to unseal TPM Disk Unlock Key" fi fi diff --git a/initrd/bin/kexec-save-default b/initrd/bin/kexec-save-default index 85ac3f27e..c3283f611 100755 --- a/initrd/bin/kexec-save-default +++ b/initrd/bin/kexec-save-default @@ -5,24 +5,24 @@ set -e -o pipefail . /etc/functions while getopts "b:d:p:i:" arg; do - case $arg in - b) bootdir="$OPTARG" ;; - d) paramsdev="$OPTARG" ;; - p) paramsdir="$OPTARG" ;; - i) index="$OPTARG" ;; - esac + case $arg in + b) bootdir="$OPTARG" ;; + d) paramsdev="$OPTARG" ;; + p) paramsdir="$OPTARG" ;; + i) index="$OPTARG" ;; + esac done if [ -z "$bootdir" -o -z "$index" ]; then - die "Usage: $0 -b /boot -i menu_option " + die "Usage: $0 -b /boot -i menu_option " fi if [ -z "$paramsdev" ]; then - paramsdev="$bootdir" + paramsdev="$bootdir" fi if [ -z "$paramsdir" ]; then - paramsdir="$bootdir" + paramsdir="$bootdir" fi bootdir="${bootdir%%/}" @@ -33,106 +33,213 @@ TMP_MENU_FILE="/tmp/kexec/kexec_menu.txt" ENTRY_FILE="$paramsdir/kexec_default.$index.txt" HASH_FILE="$paramsdir/kexec_default_hashes.txt" + +lvm_suggest=$(lvm vgscan|awk -F '"' {'print $1'}|tail -n +2) +num_lvm=$(echo "$lvm_suggest"|wc -l) +if [ "$num_lvm" -eq 1 ] && [ -n "$lvm_suggest" ]; then + lvm_volume_group=$lvm_suggest +elif [ -z "$lvm_suggest" ]; then + num_lvm=0 +fi + +devices_suggest=$(blkid | cut -d ':' -f 1 | while read device;do cryptsetup isLuks "$device";if [ $(echo $?) == 0 ]; then echo "$device";fi; done | sort) +num_devices=$(echo "$devices_suggest"|wc -l) +if [ "$num_devices" -eq 1 ]; then + key_devices=$devices_suggest +else + devices_suggest=$(echo $devices_suggest) +fi + + if [ ! -r "$TMP_MENU_FILE" ]; then - die "No menu options available, please run kexec-select-boot" + die "No menu options available, please run kexec-select-boot" fi -entry=`head -n $index $TMP_MENU_FILE | tail -1` +entry=$(head -n "$index" $TMP_MENU_FILE | tail -1) if [ -z "$entry" ]; then - die "Invalid menu index $index" + die "Invalid menu index $index" fi KEY_DEVICES="$paramsdir/kexec_key_devices.txt" KEY_LVM="$paramsdir/kexec_key_lvm.txt" save_key="n" + if [ "$CONFIG_TPM" = "y" ]; then - if [ ! -r "$KEY_DEVICES" ]; then - read \ - -n 1 \ - -p "Do you wish to add a disk encryption to the TPM [y/N]: " \ - add_key_confirm - echo - - if [ "$add_key_confirm" = "y" \ - -o "$add_key_confirm" = "Y" ]; then - lvm_suggest="e.g. qubes_dom0 or blank" - devices_suggest="e.g. /dev/sda2 or blank" - save_key="y" - fi - else - read \ - -n 1 \ - -p "Do you want to reseal a disk key to the TPM [y/N]: " \ - change_key_confirm - echo - - if [ "$change_key_confirm" = "y" \ - -o "$change_key_confirm" = "Y" ]; then - old_lvm_volume_group="" - if [ -r "$KEY_LVM" ]; then - old_lvm_volume_group=`cat $KEY_LVM` || true - old_key_devices=`cat $KEY_DEVICES \ - | cut -d\ -f1 \ - | grep -v "$old_lvm_volume_group" \ - | xargs` || true - else - old_key_devices=`cat $KEY_DEVICES \ - | cut -d\ -f1 | xargs` || true - fi - - lvm_suggest="was '$old_lvm_volume_group'" - devices_suggest="was '$old_key_devices'" - save_key="y" - fi - fi - - if [ "$save_key" = "y" ]; then - echo "+++ LVM volume groups (lvm vgscan): " - lvm vgscan || true - - read \ - -p "Encrypted LVM group? ($lvm_suggest): " \ - lvm_volume_group - - echo "+++ Block devices (blkid): " - blkid || true - - read \ - -p "Encrypted devices? ($devices_suggest): " \ - key_devices - - save_key_params="-s -p $paramsdev" - if [ -n "$lvm_volume_group" ]; then - save_key_params="$save_key_params -l $lvm_volume_group $key_devices" - else - save_key_params="$save_key_params $key_devices" - fi - echo "Running kexec-save-key with params: $save_key_params" - kexec-save-key $save_key_params \ - || die "Failed to save the disk key" - fi + if [ ! -s "$KEY_DEVICES" ]; then + read \ + -n 1 \ + -p "Do you wish to add a Disk Unlock Key to the TPM [Y/n]: " \ + add_key_confirm + echo + + if [ "$add_key_confirm" = "y" ] || [ "$add_key_confirm" = "Y" ] || [ -z "$add_key_confirm" ]; then + if [ "$num_lvm" -gt 1 ]; then + //untested + selected_lvmdev_not_existing=1 + while [ $selected_lvmdev_not_existing -ne 0 ];do + { + read \ + -p "Encrypted LVM group? choose between: $lvm_suggest: " \ + lvm_volume_group + + result=$(echo "$lvm_suggest" | grep -q "$lvm_volume_group") || selected_lvmdev_not_existing=1 + if [ $? == 0 ]; then + selected_lvmdev_not_existing=0 + fi + };done + elif [ "$num_lvm" -eq 1 ]; then + echo "Single Encrypted LVM group found at $lvm_suggest. Using it." + lvm_volume_group=$lvm_suggest + else + echo "No encrypted LVM Group found." + fi + + if [ "$num_devices" -gt 1 ]; then + selected_luksdev_not_existing=1 + while [ $selected_luksdev_not_existing -ne 0 ];do + { + read \ + -p "Encrypted devices? (choose between: $devices_suggest): " \ + key_devices + + result=$(echo "$devices_suggest" | grep -q "$key_devices") || selected_luksdev_not_existing=1 + if [ $? == 0 ]; then + selected_luksdev_not_existing=0 + fi + };done + elif [ "$num_devices" -eq 1 ]; then + echo "Single Encrypted Disk found at $devices_suggest. Using it." + key_devices=$devices_suggest + else + echo "No encrypted devices found." + fi + + save_key="y" + else + die "User chose to not add Disk Unlock Key to the TPM" + fi + else + read \ + -n 1 \ + -p "Do you want to reseal a Disk Unlock Key to the TPM [Y/n]: " \ + change_key_confirm + echo + + if [ "$change_key_confirm" = "y" ] || [ "$change_key_confirm" = "Y" ] || [ -z "$change_key_confirm" ]; then + old_lvm_volume_group="" + if [ -r "$KEY_LVM" ]; then + old_lvm_volume_group=$(cat "$KEY_LVM") || true + old_key_devices=$(cat "$KEY_DEVICES" \ + | cut -d\ -f1 \ + | grep -v "$old_lvm_volume_group" \ + | xargs) || true + else + old_key_devices=$(cat "$KEY_DEVICES" \ + | cut -d\ -f1 | xargs) || true + fi + + lvm_suggest="$old_lvm_volume_group" + devices_suggest="$old_key_devices" + save_key="y" + else + echo -e "\n\nTo set a new Disk Unlock Key passphrase, different then Disk Recovery Key passphrase, resealing the Disk Unlock key to the TPM is needed.\n\nThe actual default boot option have been invalidated by a firmware upgrade or a firmware tampering.\nIf you are the origin of the change, you have already resealed TOTP/HOTP, prompted from TPM measurements mismatches.\n\nIt is strongly advised to set a new default boot option, which will add the Disk Unlock Key to the TPM.\n\nThe Disk Unlock Key passphrase you will choose at this step will be required of you at each machine startup and will protect the Disk Recovery Key passphrase from interested eyes.\n\nBy selecting a Disk Unlock Key passphrase, a camera that would see you type your Disk Unlock Key passphrase will only be able to access the content of your hard drive on this computer.\n\nMore critically, someone knowing your Disk Recovery Key passphrase would just have to clone your disk (which takes 30 minutes) and be able to access its content from any other computer later on.\nConsider yourself warned.\n" + die "User refused to reseal the Disk Unlock Key to the TPM" + fi + fi + + if [ "$save_key" = "y" ]; then + if [ -n "$old_key_devices" ] || [ -n "$old_lvm_volume_group" ]; then + read \ + -n 1 \ + -p "Do you want to reuse configured Encrypted LVM groups/Block devices? (Y/n):" \ + reuse_past_devices + echo + if [ "$reuse_past_devices" = "y" ] || [ "$reuse_past_devices" = "Y" ] || [ -z "$reuse_past_devices" ]; then + if [ -z "$key_devices" ] && [ -n "$old_key_devices" ]; then + key_devices="$old_key_devices" + fi + if [ -z "$lvm_volume_group" ] && [ -n "$old_lvm_volume_group" ]; then + lvm_volume_group="$old_lvm_volume_group" + fi + else + if [ "$num_lvm" -eq 1 ]; then + echo "Single Encrypted LVM group found at $lvm_suggest. Using it." + lvm_volume_group="$lvm_suggest" + elif [ "$num_lvm" -gt 1 ]; then + //untested + selected_lvmdev_not_existing=1 + while [ $selected_lvmdev_not_existing -ne 0 ];do + { + read \ + -p "Encrypted LVM group? (choose between: $lvm_suggest): " \ + lvm_volume_group + + result=$(echo "$lvm_suggest" | grep -q "$lvm_volume_group") || selected_lvmdev_not_existing=1 + if [ $? == 0 ]; then + selected_lvmdev_not_existing=0 + fi + };done + else + echo "No encrypted LVM Group found." + fi + + if [ "$num_devices" -eq 1 ]; then + echo "Single Encrypted Disk found at $devices_suggest. Using it." + key_devices="$devices_suggest" + elif [ "$num_devices" -gt 1 ]; then + selected_luksdev_not_existing=1 + while [ $selected_luksdev_not_existing -ne 0 ];do + { + read \ + -p "Encrypted devices? (choose between: $devices_suggest): " \ + key_devices + + result=$(echo "$devices_suggest" | grep -q "$key_devices") || selected_luksdev_not_existing=1 + if [ $? == 0 ]; then + selected_luksdev_not_existing=0 + fi + };done + else + echo "No encrypted devices found." + fi + fi + fi + + save_key_params="-s -p $paramsdev" + if [ -n "$lvm_volume_group" ]; then + save_key_params="$save_key_params -l $lvm_volume_group $key_devices" + elif [ -n "$key_devices" ]; then + save_key_params="$save_key_params $key_devices" + else + die "No LVM Group nor encrypted devices provided." + fi + fi + + echo -e "\nRunning kexec-save-key with params: $save_key_params\n" + kexec-save-key $save_key_params \ + || die "Failed to save the Disk Unlock Key" fi # try to switch to rw mode mount -o rw,remount $paramsdev if [ ! -d $paramsdir ]; then - mkdir -p $paramsdir \ - || die "Failed to create params directory" + mkdir -p $paramsdir \ + || die "Failed to create params directory" fi rm "$paramsdir/kexec_default.*.txt" 2>/dev/null || true echo "$entry" > $ENTRY_FILE cd $bootdir && kexec-boot -b "$bootdir" -e "$entry" -f | \ - xargs sha256sum > $HASH_FILE \ + xargs sha256sum > $HASH_FILE \ || die "Failed to create hashes of boot files" if [ ! -r $ENTRY_FILE -o ! -r $HASH_FILE ]; then - die "Failed to write default config" + die "Failed to write default config" fi # sign and auto-roll config counter extparam= if [ "$CONFIG_TPM" = "y" ]; then - extparam=-u + extparam=-u fi kexec-sign-config -p $paramsdir $extparam \ || die "Failed to sign default config" diff --git a/initrd/bin/kexec-save-key b/initrd/bin/kexec-save-key index 2ea17f637..01219fcb6 100755 --- a/initrd/bin/kexec-save-key +++ b/initrd/bin/kexec-save-key @@ -1,5 +1,5 @@ #!/bin/sh -# Generate a TPM key used to unlock LUKS disks +# Generate a TPM Disk Unlock Key used to unlock LUKS disks set -e -o pipefail . /etc/functions diff --git a/initrd/bin/kexec-seal-key b/initrd/bin/kexec-seal-key index 46980af8e..4243ec7ba 100755 --- a/initrd/bin/kexec-seal-key +++ b/initrd/bin/kexec-seal-key @@ -1,5 +1,5 @@ #!/bin/sh -# This will generate a disk encryption key and seal / ecncrypt +# This will generate a Disk Unlock Key and seal / encrypt # with the current PCRs and then store it in the TPM NVRAM. # It will then need to be bundled into initrd that is booted. set -e -o pipefail @@ -32,23 +32,37 @@ if [ -r "$KEY_LVM" ]; then die "No LVM volume group defined for activation" fi lvm vgchange -a y $VOLUME_GROUP \ - || die "$VOLUME_GROUP: unable to activate volume group" + || die "$VOLUME_GROUP: Unable to activate volume group" fi -# Key slot 0 is the manual recovery pass phrase -# that they user entered when they installed Qubes, -# key slot 1 is the one that we've generated. -read -s -p "Enter disk recovery key: " disk_password -echo -n "$disk_password" > "$RECOVERY_KEY" -echo - -read -s -p "New disk unlock password for booting: " key_password -echo -read -s -p "Repeat unlock code: " key_password2 -echo +# Key slot 0 is the Disk Recovery Key pass phrase +# that the user/OEM entered when they installed/reencrypted the Operating System (LUKS container) +# key slot 1 is the Disk Unlock Key that the user generated. +if [ -z "$oem_luks_new_Disk_Recovery_Key" ]; then + read -s -p "Enter Disk Recovery Key passphrase: " disk_password + echo -n "$disk_password" > "$RECOVERY_KEY" + echo +else + echo -n "$oem_luks_new_Disk_Recovery_Key" > "$RECOVERY_KEY" +fi -if [ "$key_password" != "$key_password2" ]; then - die "Key passwords do not match" +if [ -z "$oem_luks_Disk_Unlock_Key" ]; then + password_mismatch=1 + while [ "$password_mismatch" -ne 0 ];do + { + read -s -p "New Disk Unlock Key passphrase for booting Operating System: " key_password + echo + read -s -p "Repeat Disk Unlock Key passphrase: " key_password2 + echo + + if [ "$key_password" != "$key_password2" ]; then + echo "Disk Unlock Key passphrases did not match" + else + password_mismatch=0 + fi + };done +else + key_password=$(echo -n "$oem_luks_Disk_Unlock_Key") fi # Generate key file @@ -62,18 +76,18 @@ dd \ # Remove all the old keys from slot 1 for dev in `cat "$KEY_DEVICES" | cut -d\ -f1`; do - echo "++++++ $dev: Removing old key slot" - cryptsetup luksKillSlot \ - --key-file "$RECOVERY_KEY" \ - $dev 1 \ - || warn "$dev: ignoring problem" - - echo "++++++ $dev: Adding key" - cryptsetup luksAddKey \ - --key-file "$RECOVERY_KEY" \ - --key-slot 1 \ - $dev "$KEY_FILE" \ - || die "$dev: Unable to add key" + echo "++++++ $dev: Removing key slot 1" + cryptsetup luksKillSlot \ + --key-file "$RECOVERY_KEY" \ + $dev 1 \ + || warn "Removing LUKS Disk Unlock Key on $dev (key slot 1) failed. Bad passphrase or key slot 1 not existing. Continuing..." + + echo "++++++ $dev: Adding key" + cryptsetup luksAddKey \ + --key-file "$RECOVERY_KEY" \ + --key-slot 1 \ + $dev "$KEY_FILE" \ + || die "Unable to add key to $dev key slot 1. Please try again with actual LUKS Disk Recovery Key Password." done # Now that we have setup the new keys, measure the PCRs @@ -84,8 +98,8 @@ cat "$KEY_DEVICES" | cut -d\ -f1 | xargs /bin/qubes-measure-luks \ || die "Unable to measure the LUKS headers" luks_pcr=`tpm calcfuturepcr -ix 16 -if /tmp/luksDump.txt` -# Librem Key loads USB modules which changes PCR5. -# In the event Librem Key is enabled, skip verification of PCR5 +# LibremKey/Nitrokey loads USB modules which changes PCR5. +# In the event LibremKey/Nitrokey is enabled, skip verification of PCR5 if [ -x /bin/libremkey_hotp_verification ]; then pcr_5="X" else @@ -132,9 +146,13 @@ if ! tpm nv_writevalue \ # about the sealed file tpm physicalpresence -s \ || warn "Warning: Unable to assert physical presence" - - read -s -p "TPM Owner password: " tpm_password - echo + + if [ -z "$oem_TPM_Owner_Password" ]; then + read -s -p "TPM Owner password: " tpm_password + echo + else + tpm_password=$(echo -n "$oem_TPM_Owner_Password") + fi tpm nv_definespace \ -in $TPM_INDEX \ diff --git a/initrd/bin/kexec-select-boot b/initrd/bin/kexec-select-boot index ab8002fef..93c270328 100755 --- a/initrd/bin/kexec-select-boot +++ b/initrd/bin/kexec-select-boot @@ -135,7 +135,7 @@ confirm_menu_option() { if [ "$gui_menu" = "y" ]; then whiptail --clear --title "Confirm boot details" \ --menu "Confirm the boot details for $name:\n\n$option\n\n" 20 120 8 \ - -- 'y' "Boot $name" 'd' "Make $name the default" \ + -- 'd' "Make $name the default" 'y' "Boot $name" \ 2>/tmp/whiptail || die "Aborting boot attempt" option_confirm=$(cat /tmp/whiptail) @@ -176,11 +176,11 @@ scan_options() { save_default_option() { read \ -n 1 \ - -p "Saving a default will modify the disk. Proceed? (y/n): " \ + -p "Saving a default will modify the disk. Proceed? (Y/n): " \ default_confirm echo - if [ "$default_confirm" = "y" ]; then + if [ "$default_confirm" = "y" ] || [ "$default_confirm" = "Y" ] || [ -z "$default_confirm" ]; then if kexec-save-default \ -b "$bootdir" \ -d "$paramsdev" \ @@ -191,9 +191,16 @@ save_default_option() { sleep 2 default_failed="n" force_menu="n" + if [ -e /boot/reset_disk_unlock_key ]; then + mount -o remount,rw /boot + rm -f /boot/reset_disk_unlock_key + mount -o remount,ro /boot + fi return else echo "Failed to save defaults" + echo "Press Enter to continue" + read fi fi diff --git a/initrd/bin/kexec-sign-config b/initrd/bin/kexec-sign-config index 23cdf28d9..50db5749f 100755 --- a/initrd/bin/kexec-sign-config +++ b/initrd/bin/kexec-sign-config @@ -48,17 +48,39 @@ if [ -z "$param_files" ]; then die "$paramsdir: No kexec parameter files to sign" fi -for tries in 1 2 3; do - if sha256sum $param_files | gpg \ - --digest-algo SHA256 \ - --detach-sign \ - -a \ - > $paramsdir/kexec.sig \ - ; then - # successful - update the validated params - check_config $paramsdir - exit 0 - fi -done +echo -e "\nEnrolled GPG card will now digitally sign /boot config files for future tamper evidence." +echo -e "As a result, Heads will prompt you to resign those files if any modification is detected at each reboot.\n" +echo -e "Please note that system updates will modify boot configurations. The kernel, initrd, Xen and grub files are normally modified." +echo -e "As a consequence, it is recommended that you reboot and sign /boot configuration changes after upgrading system components." +echo -e "Heads will prompt you on reboot to resign those files to attest that you approve those changes.\n" +if [ -z "$oem_gpg_User_PIN" ]; then + for tries in 1 2 3; do + echo -e "\nPlease enter your GPG card's User PIN to unlock card and sign /boot config files." + if sha256sum $param_files | gpg \ + --digest-algo SHA256 \ + --detach-sign \ + -a \ + > $paramsdir/kexec.sig \ + ; then + # successful - update the validated params + check_config $paramsdir + exit 0 + fi + done +else + echo -n "$oem_gpg_User_PIN" > /tmp/oem_gpg_User_PIN + if sha256sum $param_files | gpg --pinentry-mode loopback --batch --passphrase-file /tmp/oem_gpg_User_PIN \ + --detach-sign \ + --digest-algo SHA256 \ + -a \ + > $paramsdir/kexec.sig \ + ; then + # successful - update the validated params + shred -n 10 -z -u /tmp/oem_gpg_User_PIN 2> /dev/null + check_config $paramsdir + exit 0 + fi +fi +shred -n 10 -z -u /tmp/oem_gpg_User_PIN 2> /dev/null die "$paramsdir: Unable to sign kexec hashes" diff --git a/initrd/bin/kexec-unseal-key b/initrd/bin/kexec-unseal-key index e016f5bdc..84d95ad34 100755 --- a/initrd/bin/kexec-unseal-key +++ b/initrd/bin/kexec-unseal-key @@ -1,5 +1,5 @@ #!/bin/sh -# This will unseal and unecncrypt the drive encryption key from the TPM +# This will unseal and unencrypt the drive encryption key from the TPM # The TOTP secret will be shown to the user on each encryption attempt. # It will then need to be bundled into initrd that is booted with Qubes. set -e -o pipefail @@ -24,11 +24,11 @@ tpm nv_readvalue \ || die "Unable to read key from TPM NVRAM" for tries in 1 2 3; do - read -s -p "Enter unlock password (blank to abort): " tpm_password + read -s -p "Enter LUKS Disk Unlock Key passphrase (blank to abort): " tpm_password echo if [ -z "$tpm_password" ]; then - die "Aborting unseal disk encryption key" + die "Aborting unsealing LUKS Disk Unlock Key since no Disk Unlock Key passphrase was provided." fi if tpm unsealfile \ @@ -43,7 +43,7 @@ for tries in 1 2 3; do fi pcrs - warn "Unable to unseal disk encryption key" + warn "Unable to unseal Disk Unlock Key from TPM." done die "Retry count exceeded..." diff --git a/initrd/bin/key-init b/initrd/bin/key-init index bb4c1b5c9..42f811995 100755 --- a/initrd/bin/key-init +++ b/initrd/bin/key-init @@ -6,12 +6,16 @@ set -e -o pipefail # Import user's keys gpg --import /.gnupg/keys/*.key /.gnupg/keys/*.asc 2>/dev/null || true +#echo -e "\n\nUser's GPG keys in keyring:" +#gpg --list-keys +#echo "Press Enter key to continue..." +#read # Import trusted distro keys allowed for ISO signing gpg --homedir=/etc/distro/ --import /etc/distro/keys/* 2>/dev/null || true +# Add user's keys to the list of trusted keys for ISO signing +gpg --export | gpg --homedir=/etc/distro/ --import 2>/dev/null || true + #Set distro keys trust level to ultimate (trust anything that was signed with these keys) gpg --homedir=/etc/distro/ --list-keys --fingerprint --with-colons|sed -E -n -e 's/^fpr:::::::::([0-9A-F]+):$/\1:6:/p' |gpg --homedir=/etc/distro/ --import-ownertrust 2>/dev/null || true gpg --homedir=/etc/distro/ --update-trust 2>/dev/null || true - -# Add user's keys to the list of trusted keys for ISO signing -gpg --export | gpg --homedir=/etc/distro/ --import 2>/dev/null || true diff --git a/initrd/bin/mount-usb b/initrd/bin/mount-usb index 94946675a..0886a31f0 100755 --- a/initrd/bin/mount-usb +++ b/initrd/bin/mount-usb @@ -4,6 +4,17 @@ enable_usb +#OEM reownership, when attempting to load /media/oem-provisioning, +#requires usb-storage.ko module loaded, loaded here, modifying +#PCR 5, through /sbin/insmod script. +# +#We bypass that measurement here, so the PCR 5 is the same +#when calling kexec-seal-key in OEM mode then when calling +#kexec-unseal-key in normal boot mode. +if [ -e /boot/oem ]; then + alias insmod='busybox insmod' +fi + if ! lsmod | grep -q usb_storage; then insmod /lib/modules/usb-storage.ko \ || die "usb_storage: module load failed" diff --git a/initrd/bin/reencrypt-luks b/initrd/bin/reencrypt-luks new file mode 100755 index 000000000..e74af8ea2 --- /dev/null +++ b/initrd/bin/reencrypt-luks @@ -0,0 +1,93 @@ +#!/bin/sh +# Reencrypt LUKS container and change Disk Recovery Key associated passphrase (Slot 0: main slot) + +. /etc/functions +. /tmp/config + +select_luks_container() +{ + if [ -s /boot/kexec_key_devices.txt ]; then + LUKS=$(cut -d ' ' -f1 /boot/kexec_key_devices.txt) + else + #generate a list of devices to choose from that contain a LUKS header + blkid | cut -d ':' -f 1 | while read device;do cryptsetup isLuks $device;if [ $(echo $?) == 0 ]; then echo $device;fi; done | sort > /tmp/luks_devices.txt + file_selector "/tmp/luks_devices.txt" "Select LUKS container device" + if [ "$FILE" == "" ]; then + return + else + LUKS=$FILE + mount_boot + mount -o remount,rw /boot + echo "$LUKS $(cryptsetup luksUUID $LUKS)" > /boot/kexec_key_devices.txt + mount -o remount,ro /boot + fi + fi +} + +if [ $reownership_state = "luks_reencryption" ]; then + #if no USB oem-privisioning file provides actual Disk Recovery Key + if [ -z "$oem_luks_actual_Disk_Recovery_Key" ]; then + whiptail --title 'Reencrypt actual LUKS container with a new user selected strong passphrase?' \ + --msgbox "This will replace the actual Disk Recovery Key.\n\nThe passphrase associated with this key will be asked to the user in the\n following conditions:\n1-Every boot if no Disk unlock key was added to the TPM\n2-If the TPM fails (Hardware failure)\n3-If the firmware has been tampered with/upgraded/modified by the user\n\nThis process requires you to type the actual Disk Recovery Key passphrase\nand will delete the actual Disk unlock key released by the TPM into\nLUKS (slot 1) if present.\n\nAt the next prompt, you may be asked to select which file corresponds to\nthe LUKS device container. Normally, it should be /dev/sda2.\n\nHit Enter to continue." 30 90 + select_luks_container + whiptail --title 'Reencrypting LUKS container!' --msgbox \ + "Please enter current Disk Recovery Key passphrase (slot 0) to reencrypt\n LUKS container with a brand new encryption key\n\nHit Enter to continue." 30 60 + cryptsetup-reencrypt -B 32 --use-directio "$LUKS" --key-slot 0 + else + #USB "oem-privisioning" file provides actual Disk Recovery Key + echo -n "$oem_luks_actual_Disk_Recovery_Key" > /tmp/oem_luks_actual_Disk_Recovery_Key + select_luks_container + cryptsetup-reencrypt -B 32 --use-directio "$LUKS" --key-slot 0 --key-file /tmp/oem_luks_actual_Disk_Recovery_Key -h sha256 + fi + if [ $(echo $?) -ne 0 ]; then + whiptail --title 'Invalid LUKS Disk Recovery Key passphrase?' --msgbox \ + "The LUKS Disk Recovery Key password 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.\n\nTo do so, place ISO file and its signature file on root of USB drive,\n and select Boot from USB\n\nHit Enter to continue." 30 60 + shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null + continue + else + #Successfully reencrypted LUKS container with current Disk Recovery Key passphrase. Write successful state in oem file + if [ -e /boot/oem ];then + mount -o remount,rw /boot + echo "luks_reencrypted" >> /boot/oem + reownership_state="luks_password_change" + mount -o remount,ro /boot + shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null + fi + fi + continue +fi + +if [ $reownership_state == "luks_password_change" ]; then + #if actual or new Disk Recovery Key is not provisioned by USB oem-provisioning file + if [ -z "$oem_luks_actual_Disk_Recovery_Key" ] || [ -z "$oem_luks_new_Disk_Recovery_Key" ] ; then + 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 + + select_luks_container + + cryptsetup luksChangeKey "$LUKS" --key-slot 0 --tries 3 + else + #if actual and new Disk Recovery Key is provisioned by USB oem-provisioning file + select_luks_container + echo -n "$oem_luks_new_Disk_Recovery_Key" > /tmp/oem_luks_new_Disk_Recovery_Key + echo -n "$oem_luks_actual_Disk_Recovery_Key" > /tmp/oem_luks_actual_Disk_Recovery_Key + cryptsetup luksChangeKey "$LUKS" --key-slot 0 --key-file=/tmp/oem_luks_actual_Disk_Recovery_Key /tmp/oem_luks_new_Disk_Recovery_Key + fi + if [ $(echo $?) -ne 0 ]; then + 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 + shred -n 10 -z -u /tmp/oem_luks_new_Disk_Recovery_Key 2> /dev/null + shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null + continue + else + #Successfully changed LUKS Disk Recovery Key passphrase. Write successful state in oem file + if [ -e /boot/oem ];then + mount -o remount,rw /boot + echo "luks_passwd_changed" >> /boot/oem + mount -o remount,ro /boot + shred -n 10 -z -u /tmp/oem_luks_new_Disk_Recovery_Key 2> /dev/null + shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null + fi + fi + continue +fi diff --git a/initrd/bin/seal-libremkey b/initrd/bin/seal-libremkey index 7203b7198..7e5170ada 100755 --- a/initrd/bin/seal-libremkey +++ b/initrd/bin/seal-libremkey @@ -1,5 +1,5 @@ #!/bin/sh -# Retrieve the sealed TOTP secret and initialize a Librem Key with it +# Retrieve the sealed TOTP secret and initialize a LibremKey/NitroKey with it . /etc/functions @@ -29,7 +29,7 @@ tpm unsealfile \ || die "Unable to unseal HOTP secret" shred -n 10 -z -u "$HOTP_SEALED" 2> /dev/null -secret="`cat $HOTP_SECRET`" +secret="$(cat $HOTP_SECRET)" shred -n 10 -z -u "$HOTP_SECRET" 2> /dev/null # Store counter in file instead of TPM for now, as it conflicts with Heads @@ -52,19 +52,24 @@ counter_value=1 enable_usb if ! libremkey_hotp_verification info ; then - echo "Insert your Librem Key and press Enter to configure it" + echo "Insert your LibremKey/NitroKey and press Enter to configure it" read libremkey_hotp_verification info \ - || die "Unable to find Librem Key" + || die "Unable to find LibremKey/NitroKey" fi -read -s -p "Enter your Librem Key Admin PIN" admin_pin -echo +if [ -z "$oem_gpg_Admin_PIN" ]; then + read -s -p "Enter your LibremKey/NitroKey Admin PIN:" admin_pin + echo +else + admin_pin=$(echo -n "$oem_gpg_Admin_PIN") +fi -libremkey_hotp_initialize $admin_pin $secret $counter_value +libremkey_hotp_initialize "$admin_pin" "$secret" $counter_value if [ $? -ne 0 ]; then - read -s -p "Error setting HOTP secret, re-enter Admin PIN and try again:" admin_pin - libremkey_hotp_initialize $admin_pin $secret $counter_value \ + read -r -s -p "Error setting HOTP secret, re-enter Admin PIN and try again:" admin_pin + echo + libremkey_hotp_initialize "$admin_pin" "$secret" $counter_value \ || die "Setting HOTP secret failed" fi @@ -78,15 +83,15 @@ secret="" mount -o remount,rw /boot -counter_value=`expr $counter_value + 1` -echo $counter_value > $HOTP_COUNTER \ -|| die "Unable to create hotp counter file" +counter_value=$(expr $counter_value + 1) +echo "$counter_value" > $HOTP_COUNTER \ +|| die "Unable to create HOTP counter file" #sha256sum /tmp/counter-$counter > $HOTP_COUNTER \ -#|| die "Unable to create hotp counter file" +#|| die "Unable to create HOTP counter file" mount -o remount,ro /boot -echo "Librem Key initialized successfully. Press Enter to continue." +echo "LibremKey/NitroKey initialized successfully. Press Enter to continue." read exit 0 diff --git a/initrd/bin/seal-totp b/initrd/bin/seal-totp index f33449e58..d1f4df5e9 100755 --- a/initrd/bin/seal-totp +++ b/initrd/bin/seal-totp @@ -50,7 +50,7 @@ fi shred -n 10 -z -u "$TOTP_SECRET" 2> /dev/null -# 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. # # The permissions are 0 since there is nothing special diff --git a/initrd/bin/tpm-reset b/initrd/bin/tpm-reset index 8a8b9d1cc..150afbedb 100755 --- a/initrd/bin/tpm-reset +++ b/initrd/bin/tpm-reset @@ -5,30 +5,41 @@ echo '*****' echo '***** WARNING: This will erase all keys and secrets from the TPM' echo '*****' -read -s -p "New TPM owner password: " key_password -echo - -if [ -z "$key_password" ]; then - die "Empty owner password is not allowed" +if [ -z "$oem_TPM_Owner_Password" ]; then + key_password="1" + key_password2="2" +else + key_password="$oem_TPM_Owner_Password" + key_password2="$oem_TPM_Owner_Password" fi -read -s -p "Repeat owner password: " key_password2 -echo +while [ "$key_password" != "$key_password2" ]; do +{ + read -r -s -p "New TPM owner password: " key_password + echo + if [ -z "$key_password" ]; then + die "Empty TPM Owner password is not allowed" + fi + + read -r -s -p "Repeat TPM owner password: " key_password2 + echo + + if [ "$key_password" != "$key_password2" ]; then + die "TPM Owner passwords did not match" + fi +};done -if [ "$key_password" != "$key_password2" ]; then - die "Key passwords do not match" -fi # Make sure the TPM is ready to be reset tpm physicalpresence -s tpm physicalenable tpm physicalsetdeactivated -c -tpm forceclear +tpm forceclear tpm physicalenable -tpm takeown -pwdo "$key_password" +tpm takeown -pwdo "$key_password" >/dev/null 2>&1 # And now turn it all back on tpm physicalpresence -s -tpm physicalenable +tpm physicalenable >/dev/null tpm physicalsetdeactivated -c diff --git a/initrd/bin/unseal-totp b/initrd/bin/unseal-totp index c9c339b13..bb9fe20e5 100755 --- a/initrd/bin/unseal-totp +++ b/initrd/bin/unseal-totp @@ -16,7 +16,7 @@ tpm unsealfile \ -hk 40000000 \ -if "$TOTP_SEALED" \ -of "$TOTP_SECRET" \ -|| die "Unable to unseal totp secret" +|| die "Unable to unseal TOTP secret" shred -n 10 -z -u "$TOTP_SEALED" 2> /dev/null diff --git a/initrd/etc/functions b/initrd/etc/functions index 453590b84..6bd546b66 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -3,9 +3,20 @@ die() { echo >&2 "$*"; + read -p 'Hit enter to continue.' exit 1; } +debug(){ + echo >&2 "$*"; + read -p 'Hit enter to continue.' +} + +error() { + echo >&2 "$*"; + exit 1; +} + warn() { echo >&2 "$*"; } @@ -41,7 +52,7 @@ pause_recovery() { } pcrs() { - head -8 /sys/class/tpm/tpm0/pcrs + head -9 /sys/class/tpm/tpm0/pcrs } confirm_totp() @@ -118,6 +129,61 @@ enable_usb() fi } +file_selector() { + FILE="" + FILE_LIST=$1 + MENU_MSG=${2:-"Choose the file"} + # create file menu options + 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" + whiptail --clear --title "Select your File" \ + --menu "${MENU_MSG} [1-$n, a to abort]:" 20 120 8 \ + -- $MENU_OPTIONS \ + 2>/tmp/whiptail || die "Aborting" + + option_index=$(cat /tmp/whiptail) + + if [ "$option_index" = "a" ]; then + option="a" + return + fi + + option=$(head -n "$option_index" "$FILE_LIST" | tail -1) + if [ "$option" == "a" ]; then + return + fi + done + if [ -n "$option" ]; then + FILE=$option + fi + else + whiptail $CONFIG_ERROR_BG_COLOR --title 'ERROR: No Files Found' \ + --msgbox "No Files found matching the pattern. Aborting." 16 60 + exit 1 + fi +} + +mount_boot() +{ + # Mount local disk if it is not already mounted + if ! grep -q /boot /proc/mounts ; then + mount -o ro /boot \ + || recovery "Unable to mount /boot from $CONFIG_BOOT_DEV" + fi +} + confirm_gpg_card() { read \ @@ -140,7 +206,6 @@ confirm_gpg_card() || die "gpg card read failed" } - check_tpm_counter() { LABEL=${2:-3135106223} @@ -148,10 +213,15 @@ check_tpm_counter() # from it. if [ -r "$1" ]; then TPM_COUNTER=`grep counter- "$1" | cut -d- -f2` - else - warn "$1 does not exist; creating new TPM counter" - read -s -p "TPM Owner password: " tpm_password - echo + else + warn "$1 does not exist; creating new TPM counter" + if [ -z "$oem_TPM_Owner_Password" ]; then + read -s -p "TPM Owner password: " tpm_password + echo + else + tpm_password=$(echo -n "$oem_TPM_Owner_Password") + fi + tpm counter_create \ -pwdo "$tpm_password" \ -pwdc '' \ @@ -198,7 +268,8 @@ check_config() { if [ "$2" != "force" ]; then if ! sha256sum `find $1/kexec*.txt` | gpgv $1/kexec.sig - ; then - die 'Invalid signature on kexec boot params' + die 'Invalid signature on kexec boot params. Investigate/Update checksums and sign all files in /boot.' + #TODO: Show which files failed integrity check! fi fi diff --git a/initrd/init b/initrd/init index fd79d6773..b06079182 100755 --- a/initrd/init +++ b/initrd/init @@ -16,7 +16,7 @@ mkdir /proc /sys /dev /tmp /boot /media 2>&- 1>&- mount /dev 2>/dev/ttyprintk mount /proc 2>/dev/ttyprintk mount /sys 2>/dev/ttyprintk -mount /sys/firmware/efi/efivars +mount /sys/firmware/efi/efivars 2>/dev/ttyprintk # Setup the pty psudeo filesystem mkdir /dev/pts @@ -31,7 +31,6 @@ mkdir -p /tmp/secret # Now it is safe to print a banner if [ -r /etc/motd ]; then - cat /etc/motd cat /etc/motd > /dev/tty0 fi @@ -42,6 +41,15 @@ hwclock -l -s . /etc/functions . /etc/config +# Add our boot devices into the /etc/fstab, if they are defined +# in the configuration file. +if [ ! -z "$CONFIG_BOOT_DEV" ]; then + echo >> /etc/fstab "$CONFIG_BOOT_DEV /boot auto defaults,ro 0 0" +fi +if [ ! -z "$CONFIG_USB_BOOT_DEV" ]; then + echo >> /etc/fstab "$CONFIG_USB_BOOT_DEV /media auto defaults,ro 0 0" +fi + if [ "$CONFIG_COREBOOT" = "y" ]; then /bin/cbfs-init fi diff --git a/modules/gpg2 b/modules/gpg2 index 318a4cd11..566c1bec2 100644 --- a/modules/gpg2 +++ b/modules/gpg2 @@ -30,19 +30,12 @@ gpg2_configure := ./configure \ --disable-regex \ --disable-doc \ --disable-bzip2 \ - --disable-asm \ --disable-exec \ --disable-photo-viewers \ - --disable-keyserver-helpers \ --disable-ldap \ - --disable-hkp \ - --disable-finger \ - --disable-dns-srv \ - --disable-dns-cert \ --disable-regex \ --disable-nls \ --disable-all-tests \ - --disable-wks-server \ --disable-wks-tools \ --disable-gnutls \ --disable-dirmngr \ diff --git a/modules/libassuan b/modules/libassuan index 3c4e319aa..1b1d9fb6a 100644 --- a/modules/libassuan +++ b/modules/libassuan @@ -10,9 +10,7 @@ libassuan_configure := ./configure \ --host x86_64-linux-musl \ --prefix "/" \ --disable-static \ - --disable-nls \ --with-libgpg-error-prefix="$(INSTALL)" \ - --disable-asm \ libassuan_target := $(MAKE_JOBS) \ DESTDIR="$(INSTALL)" \ diff --git a/modules/libgcrypt b/modules/libgcrypt index aa7e1ef8e..d3c9dab4a 100644 --- a/modules/libgcrypt +++ b/modules/libgcrypt @@ -12,7 +12,6 @@ libgcrypt_configure := ./configure \ --disable-static \ --with-libgpg-error-prefix="$(INSTALL)" \ --disable-asm \ - --disable-nls \ libgcrypt_target := $(MAKE_JOBS) \ DESTDIR="$(INSTALL)" \ diff --git a/modules/libgpg-error b/modules/libgpg-error index 752e11aad..486eb2566 100644 --- a/modules/libgpg-error +++ b/modules/libgpg-error @@ -14,7 +14,6 @@ libgpg-error_configure := ./configure \ --disable-languages \ --disable-doc \ --disable-tests \ - --disable-asm \ libgpg-error_target := $(MAKE_JOBS) \ DESTDIR="$(INSTALL)" \ diff --git a/modules/libusb b/modules/libusb index b7fe959c4..9e63c8608 100644 --- a/modules/libusb +++ b/modules/libusb @@ -13,7 +13,6 @@ libusb_configure := ./configure\ --host i386-elf-linux\ --prefix "/"\ --disable-udev\ - --disable-tests\ # Run one build to generate the executables with the pre-defined # exec_prefix and datarootdir, then a second make to install the binaries diff --git a/modules/lvm2 b/modules/lvm2 index 91f0f53f0..bf18b818b 100644 --- a/modules/lvm2 +++ b/modules/lvm2 @@ -30,6 +30,8 @@ lvm2_configure := \ --disable-blkid_wiping \ --disable-cmirrord \ --disable-cache_check_needs_check \ + --with-thin=internal \ + --with-snapshots=internal \ --disable-thin_check_needs_check \ --with-cluster=none \ diff --git a/modules/npth b/modules/npth index e0f30c69e..a0cb09fca 100644 --- a/modules/npth +++ b/modules/npth @@ -10,9 +10,6 @@ npth_configure := ./configure \ --host x86_64-linux-musl \ --prefix "/" \ --disable-static \ - --disable-nls \ - --with-libgpg-error-prefix="$(INSTALL)" \ - --disable-asm \ npth_target := $(MAKE_JOBS) \ DESTDIR="$(INSTALL)" \ diff --git a/modules/pixman b/modules/pixman index 65a2e2008..8bd54a900 100644 --- a/modules/pixman +++ b/modules/pixman @@ -3,7 +3,7 @@ modules-$(CONFIG_CAIRO) += pixman pixman_version := 0.34.0 pixman_dir := pixman-$(pixman_version) pixman_tar := pixman-$(pixman_version).tar.gz -pixman_url := https://www.cairographics.org/releases/$(pixman_tar) +pixman_url := https://ftp.osuosl.org/pub/blfs/conglomeration/pixman/$(pixman_tar) pixman_hash := 21b6b249b51c6800dc9553b65106e1e37d0e25df942c90531d4c3997aa20a88e pixman_configure := \ diff --git a/oem-reownership/generate_diceware-eom-provisioning.sh b/oem-reownership/generate_diceware-eom-provisioning.sh new file mode 100755 index 000000000..abf7ce592 --- /dev/null +++ b/oem-reownership/generate_diceware-eom-provisioning.sh @@ -0,0 +1,66 @@ +#!/bin/bash +# 0- To use this script, install diceware first +# sudo dnf install diceware -y +# sudo apt-get install diceware -y +# +# Then +# 1- Run this script with ./generate_diceware-eom-provisioning.sh +# 2- Edit ./oem-provisioning.generated so all variiables are provisioned +# 3- Mount USB drive to /media ( eg. sudo mount /dev/sdb1 /media ) +# 4- Copy the file on USB drive ( eg. sudo cp /oem-provisioning.generated /media/oem-provisioning ) +# 5- Unmount USB drive to flush changes ( eg. sudo umount /media ) +# 6- Boot your newly received hardware with USB drive connected. +# 7- Enjoy! +# + +echo "#PLEASE KEEP THIS FILE IN A SAFE PLACE FOR FURTHER REFERENCE. " > ./oem-provisioning.generated +echo "#" >> ./oem-provisioning.generated +echo "#############" >> ./oem-provisioning.generated +echo "# IMPORTANT #" >> ./oem-provisioning.generated +echo "#############" >> ./oem-provisioning.generated +echo "# TO REMEMBER: Disk Recovery Key Passphrase (Used at system upgrades to recreate a Disk Unlock Key while setting a new boot default)" >> ./oem-provisioning.generated +echo "# !!!! IF YOU LOOSE THIS PASSPHRASE YOU'LL BE LOCKED OUT OF YOUR ENCRYPTED DISK !!!" >> ./oem-provisioning.generated +echo "# TO REMEMBER: Disk Unlock Key passphrase (Used at every boot, in between system upgrades)" >> ./oem-provisioning.generated +echo "# TO REMEMBER: GPG User PIN (Used to sign /boot config changes following system upgrades)" >> ./oem-provisioning.generated +echo "# After 3 bad attempts, you will need to unlock User PIN from Admin PIN" >> ./oem-provisioning.generated +echo "# TO REMEMBER: GPG Admin PIN (Used to manage the GPG card and to attest firmware changes you made.)" >> ./oem-provisioning.generated +echo "# After 3 bad attempts, YOU WILL BE LOCKED OUT OF THE CARD!" >> ./oem-provisioning.generated +echo "#" >> ./oem-provisioning.generated +echo "#" >> ./oem-provisioning.generated +echo "###########" >> ./oem-provisioning.generated +echo "# GPG #" >> ./oem-provisioning.generated +echo "###########" >> ./oem-provisioning.generated +echo "#The following GPG Key Admin PIN will be required from you to manage your LibremKey/Nitrokey" >> ./oem-provisioning.generated +echo "#It will be prompted from you under Heads through HOTP code generation to confirm firmware changes were yours" >> ./oem-provisioning.generated +while [[ ${#oem_gpg_Admin_PIN} -lt 8 || ${#oem_gpg_Admin_PIN} -gt 20 ]];do + oem_gpg_Admin_PIN=$(diceware -n 2) +done +echo "oem_gpg_Admin_PIN=$oem_gpg_Admin_PIN" >> ./oem-provisioning.generated +while [[ ${#oem_gpg_User_PIN} -lt 6 || ${#oem_gpg_User_PIN} -gt 20 ]];do + oem_gpg_User_PIN=$(diceware -n 2) +done +echo "#The following GPG Key User PIN will be required from you to Sign/Encrypt/Authenticate with your LibremKey/Nitrokey" >> ./oem-provisioning.generated +echo "#It will be prompted from you under Heads to confirm you are aware of /boot related changes" >> ./oem-provisioning.generated +echo "oem_gpg_User_PIN=$oem_gpg_User_PIN" >> ./oem-provisioning.generated +echo "#The following will be used to identify you publicly in generated public key from Heads." >> ./oem-provisioning.generated +echo "#If you intend to upload the generated public key online, you are invited provision the following accordingly" >> ./oem-provisioning.generated +echo "oem_gpg_real_name=" >> ./oem-provisioning.generated +echo "oem_gpg_email=" >> ./oem-provisioning.generated +echo "#The following is used to differenciate different public keys attached to the same name and e-mail address" >> ./oem-provisioning.generated +echo "oem_gpg_comment=" >> ./oem-provisioning.generated +echo "#" >> ./oem-provisioning.generated +echo "########################################" >> ./oem-provisioning.generated +echo "# LUKS Disk Encryption Key Passphrases #" >> ./oem-provisioning.generated +echo "########################################" >> ./oem-provisioning.generated +echo "#The actual Disk Recovery Key passphrase needs to match the passphrase provided by the OEM to unlock actual Disk encrypted drive" >> ./oem-provisioning.generated +echo "oem_luks_actual_Disk_Recovery_Key=" >> ./oem-provisioning.generated +echo "#The new Disk Recovery Key passphrase will replace the Disk Recovery Key password after reencrypting the container with the actual one" >> ./oem-provisioning.generated +echo "oem_luks_new_Disk_Recovery_Key=$(diceware -n 5)" >> ./oem-provisioning.generated +echo "#The Disk Unlock Key passphrase will be used to lauch default boot option at each system startup, and is bound to measured boot integrity attested by the TPM." >> ./oem-provisioning.generated +echo "oem_luks_Disk_Unlock_Key=$(diceware -n 3)" >> ./oem-provisioning.generated +echo "#" >> ./oem-provisioning.generated +echo "#################################" >> ./oem-provisioning.generated +echo "# Trusted Platform Module (TPM) #" >> ./oem-provisioning.generated +echo "#################################" >> ./oem-provisioning.generated +echo "#The TPM Owner passphrase is needed just to own the machine. It is suggested to use the same passphrase as in Admin PIN to limit the number of secrets to remember." >> ./oem-provisioning.generated +echo "oem_TPM_Owner_Password=$oem_gpg_Admin_PIN" >> ./oem-provisioning.generated diff --git a/oem-reownership/oem-provisioning.example b/oem-reownership/oem-provisioning.example new file mode 100644 index 000000000..b0e5017fa --- /dev/null +++ b/oem-reownership/oem-provisioning.example @@ -0,0 +1,198 @@ +########### +# OEM # +########### +# To activate OEM reownership wizard, under Heads recovery console, do: +# mount /boot +# mount -o remount,rw /boot +# echo "oem_name=COMPANY NAME" > /boot/oem +# mount -o remount,ro /boot +# reboot +# +# To activate OEM automatic provisioning, the content of this file needs to be found by Heads under: +# /media/oem-provisioning +# By default, the USB drive is mounted from /dev/sdb1 but "mount-usb" will find the usb drive and mount it under /media +# +# Replace variables content with your own! +# +#The following needs to be put in /boot/oem for OEM name to be shown at OEM Reownership wizard first screen. Else it is going to be "your OEM". +#oem_name=Insurgo Open Technologies +# +#On a recovery shell, type the UP arrow key until you reach top of the history buffer. A command is proposed for you to change "YOUR COMPANY" +# to your own. The hardware is then ready to ship and the wizard will accompany the user in reowning the hardware and OEM secrets on next reboot. +# +# You should invite the user into using "generate_diceware-eom-provisioning.sh" script in the current directory, +# which uses diceware to prefeed "oem-provisioning.generated" with proper secrets. +# The user would then need to put that file under "oem-provisioning" on the root of a dedicated USB drive and connect on first boot of +# received hardware to reduce user errors and friction of having to enter those secrets manually. + +######### +# GPG # +######### +# GPG card function in Heads: +# The LibremKey/NitroKey is a traditional GPG card added with HMAC-based One-time Password (HOTP) which permits +# to seal integrity measurements into the GPG card memory. +# +# As a functional result, at each boot, the card will flash its LED green if the measured boot integrity +# is atttested or red in case of a mismatch. This provable security measure is called tamper-evidence and +# informs the user that the Firmware (BIOS chips content) has been tampered with, or modified, and doesn't +# match expected measurements expected by the Trusted Platform Module (TPM) and validated by the GPG card. +# +# Heads traditionally stores Trusted Module Platform (TPM) Time-based One-time Password (TOTP) code in a +# smartphone through the scanning of a QR code into an OTP authenticator application when the TPM is reowned or +# when a firmware update is applied. Through the reownership process, the firmware will be modified by inserting +# public PGP key into the firmware, which will invalidate measurements and require the TOTP/HOTP to be resealed. +# The TPM itself will be reowned by the user, requesting him to set a passphrase. +# +# *** You should use both TOTP/HOTP so you can still validate attested integiryt in case your GPG card gets lost *** +# +# HOTP/TOTP are functionally similar, while the LibremKey/Nitrokey permits to validate integrity visually in an +# instant without having to unlock the smartphone, open the OTP application and verify that a 6 digits code there +# is the same that is shown on the screen. +# HOTP LibremKey/Nitrokey feature is complementory to the TOTP and shares the same codebase. +# +# Heads also depends on the GPG card to store used private key outside of prying eyes, securely stored on the +# Smartcard. When factory resetting the card, only the public key is inserted into the rom, which is used +# to automatically validate the integiryt of /boot files through checksuming and validating the the result +# matches what is signed with the private key on the GPG card. +# +# Heads will warn the user each time boot configuration changes. +# That will happen when the Operating System applies core system updates (Xen, Kernel, initrd (drivers) +# and grub configuration) while notifying the user of any addition/supression of files expected to be found +# in the /boot partition. +# +# GPG usage in Heads: +# Heads will prompt the user for: +# User PIN: +# Sign boot configuration changes. +# Admin PIN: +# Seal Firmware changes through HOTP +# +# IMPORTANT: +# The user should always reboot the system and sign configuration changes as soon as possible after system upgrades +# to attest the responsibility and ownership of the changes. +# +# The user should always be cautious about TOTP/HOTP errors if he didn't update the firmware himself. +# +# Heads primary goal is to attest of the integrity of the firmware and /boot files. +# That integrity attestation is based on those two practices that REQUIRES TO BE FOLLOWED. +# +# PIN Notes: GPG PINs are protected in the SmartCard. After 3 bad attempts, the SmartCard locks that account. +# When the User PIN is locked, the Admin PIN can be used to unlock User PIN. +# When the Admin PIN is locked, a Reset Code can be used to unlock Admin PIN. +# This is not provisioned by default. You will have to set one manually yourself. +# +# You can define an additional "Reset Code" to reset the Admin PIN manually by doing: +# gpg --card-edit +# admin +# passwd +# 4 - set the Reset Code +# Type Admin PIN +# +#GPG SmartCard desired Admin PIN to provision GPG factory reset. +# Admin PIN manages Admin functions of the card through gpg --edit-card admin functions, +# In Heads, the Admin PIN is required to seal HOTP secret into NitroKey/LibremKey when firmware has been modified. +# +# NOTES: If the GPG card is lost, the user won't be able to seal firmware changes through HOTP. +# Size constaints: minimum 8 characters, maximum 20 characters, WITHOUT SPACES! +# (Else HOTP cannot be sealed. It's a seal-libremkey limitation) +# No need to go crazy here. Remember that 3 bad attempts locks the account. One or two Diceware words are enough. +# Use KeepassXC password manager or something like https://www.rempe.us/diceware/#eff +oem_gpg_Admin_PIN=InsurgoTech +# +#GPG SmartCard desired User PIN to provision GPG factory reset. +# User PIN manages user functions of the card. It is used to encrypt files and e-mails, sign files and e-mails +# and authenticate the user in daily operations when used in combination with the public key generated. +# That public key needs to be kept, as it is impossible to export it from the smartcard. +# In Heads, the User PIN is required to sign boot configuration changes. +# At each boot, the imported public key counterpart is used to validate the checksums of the files signed with the card. +# +# NOTES: If the GPG card is lost, the user won't be able to sign system changes. +# Size constaints: minimum 6 characters, maximum 20 characters +# No need to go crazy here. Remember that 3 bad attempts locks the account. One or two Diceware words are enough. +# Use KeepassXC password manager or something like https://www.rempe.us/diceware/#eff +oem_gpg_User_PIN=Insurgo +#GPG SmartCard desired Real Name to provision GPG factory reset. +# This will be used to construct the ID of the public key: "Real Name (Comment) email@address.org" +# +# Size constaints: minimum 5 characters. +oem_gpg_real_name=Insurgo Integrity Delivered Attestation Attestation LibremKey +#GPG SmartCard desired E-mail address to provision GPG factory reset. +# This will be used to construct the ID of the public key: "Real Name (Comment) email@address.org" +# Note that some services requires that e-mail address to be real and will send an e-mail to validate it. +# If you intend to use the GPG card to encrypt/sign e-mails, this is a good idea to provide main e-mail account here. +oem_gpg_email=insurgo@riseup.net +#GPG SmartCard desired Comment to provision GPG factory reset. +# This will be used to construct the ID of the public key: "Real Name (Comment) email@address.org" +# If you have multiple cards associated with the same E-mail address, this is a good place to name it's usage difference +oem_gpg_comment=FACTORY RESET ME + +########## +# LUKS # +########## +# LUKS containers are used in Linux to encrypt whole filesystems. +# The whole idea behind OEM reownership depends on the LUKS reencryption of the container from the user when hardware +# is received. Otherwise, the OEM would know the cloned image LUKS Disk Recovery Key and could hand it to authorities. +# This provisioning wizard starts by asking you to enter the actual LUKS Disk Recovery Key passphrase to reencrypt the +# container completely, before changing it's passphrase with user selected one. +# +# This LUKS Disk Recovery Key, if provided by the OEM **** SHOULD NOT BE MODIFIED ***** +oem_luks_actual_Disk_Recovery_Key=InsurgoTech +# This is where you want to define your new Disk Recovery Key passphrase, which will be associated to the reencrypted LUKS +# container after the OEM wizard is over and become the Disk Recovery Key passphrase. +# +# This provisioning wizard continues by asking you to enter the desired LUKS Disk Recovery Key passphrase and changes +# it. +# +# The Disk Recovery Key will be prompted to the user in the following cases: +# 1-Every boot if no Disk Unlock Key was added to the TPM (NOT RECOMMENDED! could be captured and used on cloned disk) +# 2-If the TPM fails (Hardware failure) +# 3-If the firmware has been tampered with/upgraded/modified by the user +# +# NOTES: If the Disk Recovery Key Passphrase is lost, the user won't be able to set a new Disk Unlock Key. +# More importantly, in the case of a Operating System core update (Xen, Kernel, initrd (drivers) or grub config, +# the Default Boot option will be invalidated, and the only way to boot the system will be by typing this +# Disk Recovery Key Passphrase. ********** CHOOSE IT CAREFULLY SO YOU CAN EASILY REMEMBER IT *********** +# +# Size constaints: select a Diceware passphrase of at least 3 words. 6 is better. +# No need to go crazy here. It's better to have a shorter but strong passphrase you remember and not type often +# then a strong passphrase that locks you out of the system and requires you to reinstall. +# Use KeepassXC password manager or something alike https://www.rempe.us/diceware/#eff +oem_luks_new_Disk_Recovery_Key=InsurgoTech +# Disk Unlock Key Passphrase is the passphrase the user will be required to type under Heads to start the system. +# +# The Disk Unlock Key is another security feature enforced by Heads that makes your computer more trustworthy. +# The Disk Unlock Key is released by the Trusted Platform Module (TPM), a cryptographic component on which +# depends Heads to measure and attest firmware integrity, and released only if the measurements of the firmware +# are intact (sealed). In the case the firmware has been modified, that the user lost/forgot his GPG card, +# the Disk Unlock key passphrase will refuse to release the actual Disk Unlock Key and will not boot, unless +# you to type the Disk Recovery Key passphrase. +# +# Heads would not be able to unseal neither TOTP/HOTP in case measurements mismatche and will warn the user. +# +# The Disk Unlock Key passphrase will also not be able to unlock the disk if the LUKS header is not +# consistent with what was sealed into the TPM when selecting a default boot option. +# +# Functionnaly, selecting a default boot option and setting a Disk Unlock Key is a good security measure against +# prying eyes, let them be camera recording or over the shoulder passphrase capture. +# Since that Key is bounded with firmware integrity measurements from the TPM, that passphrase is bound to this +# computer only. +# +# A third party which would clone the disk and attempt to access its content later would succeed only if +# Disk Recovery Key passphrase was typed, not the Disk Unlock Key passphrase. +# +# Size constaints: Best is to select a Diceware passphrase of at least 4 words. 6+ is better. +# Use KeypassXC password manager or something like https://www.rempe.us/diceware/#eff +# No need to go crazy here. An attacker would have 3 attempts at a time when booting Heads. +# Use KeepassXC password manager or something like https://www.rempe.us/diceware/#eff +# You will be prompted to change this passphrase at every core Operating System upgrades since the default boot +# option will be modified. +oem_luks_Disk_Unlock_Key=Insurgo + +################################### +# Trusted Platform Module (TPM) # +################################### +# The TPM passphrase is required when sealing the Disk Unlock Key when selecting a new default boot option, +# combined with the GPG User PIN. +# +# It is recommended to reuse GPG Admin Passphrase/Password here, to not unecessarily multiply secrets to remember. +oem_TPM_Owner_Password=InsurgoTech From e49b184ad37e1fddd4c86955a9bb4c1ee7a5ebfe Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Tue, 23 Apr 2019 16:53:49 -0400 Subject: [PATCH 02/91] - OEM mode is enforced on HOTP/TOTP sealed clean hardware. - OEM is enforced by touching /boot/oem - OEM can be provisioned automatically if /media/oem-provisioning exists which feeds all the secrets automatically. - LUKS rencryption script added, which reencrypts and change Disk Recevory Key passphrase - LibremKey/Nitrokey factory reset script added, which takes user input first and then change key size, generate keys, exports them and flash rom. -Todo: Reset code should be added later on. (To unlock Admin. Else, a DoS is possible on a USB key) - Contains uniformaization of langage. - some shellcheck improved code - LUKS Disk Unlock Key works properly -LVM volumes and disk devices are automatically detected - GPG modules were retouched to remove invalid configure options which generated warnings - LibremKey/Nitrokey is named everywhere for proper credit of partnership for HOTP ... And a lot of other smaller fixes... --- .gitlab-ci.yml | 25 ++ boards/x230/x230.config | 5 +- config/coreboot-x230.config | 2 +- config/linux-x230.config | 4 - initrd/.ash_history | 15 +- .../bin/factory-reset-nitrokey-libremkey.sh | 232 ++++++++++++ initrd/bin/flash-gui.sh | 4 +- initrd/bin/flash.sh | 9 + initrd/bin/gpg-gui.sh | 12 +- initrd/bin/gui-init | 347 ++++++++++++++++-- initrd/bin/kexec-insert-key | 14 +- initrd/bin/kexec-save-default | 271 +++++++++----- initrd/bin/kexec-save-key | 2 +- initrd/bin/kexec-seal-key | 82 +++-- initrd/bin/kexec-select-boot | 13 +- initrd/bin/kexec-sign-config | 46 ++- initrd/bin/kexec-unseal-key | 8 +- initrd/bin/key-init | 10 +- initrd/bin/mount-usb | 11 + initrd/bin/reencrypt-luks | 93 +++++ initrd/bin/seal-libremkey | 33 +- initrd/bin/seal-totp | 2 +- initrd/bin/tpm-reset | 33 +- initrd/bin/unseal-totp | 2 +- initrd/etc/functions | 85 ++++- initrd/init | 12 +- modules/gpg2 | 7 - modules/libassuan | 2 - modules/libgcrypt | 1 - modules/libgpg-error | 1 - modules/libusb | 1 - modules/lvm2 | 2 + modules/npth | 3 - modules/pixman | 2 +- .../generate_diceware-eom-provisioning.sh | 66 ++++ oem-reownership/oem-provisioning.example | 198 ++++++++++ 36 files changed, 1417 insertions(+), 238 deletions(-) create mode 100644 .gitlab-ci.yml create mode 100755 initrd/bin/factory-reset-nitrokey-libremkey.sh create mode 100755 initrd/bin/reencrypt-luks create mode 100755 oem-reownership/generate_diceware-eom-provisioning.sh create mode 100644 oem-reownership/oem-provisioning.example diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 000000000..ac691c8ee --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,25 @@ +image: insurgotech/fedora-29_heads-ci + +stages: + - build + +build: + stage: build + cache: + paths: + - ./ + cache: + untracked: true + paths: + - ./git + script: + - make BOARD=x230-flash + - make BOARD=x230 + - echo "x230-flash hashes:" + - cat ./build/x230-flash/hashes.txt + - echo "x230 hashes:" + - cat ./build/x230/hashes.txt + artifacts: + paths: + - ./build/x230-flash/x230-flash.rom + - ./build/x230/coreboot.rom diff --git a/boards/x230/x230.config b/boards/x230/x230.config index 1d46ba920..0d593e1fc 100644 --- a/boards/x230/x230.config +++ b/boards/x230/x230.config @@ -17,8 +17,11 @@ CONFIG_QRENCODE=y CONFIG_TPMTOTP=y CONFIG_DROPBEAR=y +#CONFIG_SLANG=y +#CONFIG_NEWT=y CONFIG_CAIRO=y CONFIG_FBWHIPTAIL=y +CONFIG_LIBREMKEY=y CONFIG_LINUX_USB=y CONFIG_LINUX_E1000E=y @@ -28,7 +31,7 @@ export CONFIG_BOOTSCRIPT=/bin/gui-init export CONFIG_BOOT_REQ_HASH=n export CONFIG_BOOT_REQ_ROLLBACK=n export CONFIG_BOOT_KERNEL_ADD="intel_iommu=on intel_iommu=igfx_off" -export CONFIG_BOOT_KERNEL_REMOVE="quiet" +export CONFIG_BOOT_KERNEL_REMOVE="" export CONFIG_BOOT_DEV="/dev/sda1" export CONFIG_BOOT_GUI_MENU_NAME="Thinkpad X230 Heads Boot Menu" export CONFIG_USB_BOOT_DEV="/dev/sdb1" diff --git a/config/coreboot-x230.config b/config/coreboot-x230.config index 65b13b581..eab78307a 100644 --- a/config/coreboot-x230.config +++ b/config/coreboot-x230.config @@ -19,6 +19,6 @@ CONFIG_PAYLOAD_LINUX=y CONFIG_PAYLOAD_FILE="../../build/x230/bzImage" CONFIG_PAYLOAD_OPTIONS="" # CONFIG_PXE is not set -CONFIG_LINUX_COMMAND_LINE="intel_iommu=igfx_off quiet" +CONFIG_LINUX_COMMAND_LINE="intel_iommu=igfx_off quiet loglevel=3" CONFIG_LINUX_INITRD="../../build/x230/initrd.cpio.xz" CONFIG_DEBUG_SMM_RELOCATION=y diff --git a/config/linux-x230.config b/config/linux-x230.config index 44bd5ac6b..353670dfb 100644 --- a/config/linux-x230.config +++ b/config/linux-x230.config @@ -56,7 +56,6 @@ CONFIG_KEXEC_FILE=y CONFIG_PHYSICAL_ALIGN=0x1000000 # CONFIG_MODIFY_LDT_SYSCALL is not set # CONFIG_SUSPEND is not set -CONFIG_ACPI_VIDEO=y CONFIG_PCI_MSI=y # CONFIG_HT_IRQ is not set CONFIG_PCI_IOV=y @@ -184,9 +183,7 @@ CONFIG_MFD_SYSCON=y CONFIG_DRM=y CONFIG_DRM_I915=y CONFIG_FB_VESA=y -CONFIG_BACKLIGHT_LCD_SUPPORT=y # CONFIG_LCD_CLASS_DEVICE is not set -CONFIG_BACKLIGHT_CLASS_DEVICE=y # CONFIG_BACKLIGHT_GENERIC is not set CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_USB=y @@ -218,7 +215,6 @@ CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y # CONFIG_PROC_SYSCTL is not set # CONFIG_PROC_PAGE_MONITOR is not set -CONFIG_TMPFS=y # CONFIG_MISC_FILESYSTEMS is not set CONFIG_NLS_DEFAULT="utf8" CONFIG_NLS_CODEPAGE_437=y diff --git a/initrd/.ash_history b/initrd/.ash_history index 996900531..5c292979e 100644 --- a/initrd/.ash_history +++ b/initrd/.ash_history @@ -1,17 +1,22 @@ -#remove invalid kexec_* signed files -mount /dev/sda1 /boot && mount -o remount,rw /boot && rm /boot/kexec* && mount -o remount,ro /boot +#To activate OEM reownership wizard, under Heads recovery console, do: +mount /boot +mount -o remount,rw /boot && echo "oem_name=COMPANY NAME" > /boot/oem && mount -o remount,ro /boot && reboot +#remove invalid kexec.sig signed checksum file +mount /dev/sda1 /boot && mount -o remount,rw /boot && rm /boot/kexec.sig && mount -o remount,ro /boot #Generate keys from GPG smartcard: -mount-usb && gpg --home=/.gnupg/ --card-edit +usb-init && gpg --home=/.gnupg/ --card-edit #Copy generated public key, private_subkey, trustdb and artifacts to external media for backup: -mount -o remount,rw /media && mkdir -p /media/gpg_keys; gpg --export-secret-keys --armor email@address.com > /media/gpg_keys/private.key && gpg --export --armor email@address.com > /media/gpg_keys/public.key && gpg --export-ownertrust > /media/gpg_keys/otrust.txt && cp -r ./.gnupg/* /media/gpg_keys/ 2> /dev/null +mount -o remount,rw /media && mkdir -p /media/gpg_keys; gpg --export-secret-keys --armor email@address.com > /media/gpg_keys/private.key && gpg --export --armor email@address.com > /media/gpg_keys/public.key && cp -r ./.gnupg/* /media/gpg_keys/ 2> /dev/null #Insert public key and trustdb export into reproducible rom: -cbfs -o /media/coreboot.rom -a "heads/initrd/.gnupg/keys/public.key" -f /media/gpg_keys/public.key && cbfs -o /media/coreboot.rom -a "heads/initrd/.gnupg/keys/otrust.txt" -f /media/gpg_keys/otrust.txt +cbfs -o /media/coreboot.rom -a "heads/initrd/.gnupg/keys/public.key" -f /media/gpg_keys/public.key #Flush changes to external media: mount -o,remount ro /media #Flash modified reproducible rom with inserted public key and trustdb export from precedent step. Flushes actual rom's keys (-c: clean): flash.sh -c /media/coreboot.rom #Attest integrity of firmware as it is seal-totp +#Sign a manually verified ISO with your GPG key so you can boot it from Heads +mount-usb && gpg --card-status && gpg --detach-sig /media/some.iso #Verify Intel ME state: cbmem --console | grep '^ME' cbmem --console | less diff --git a/initrd/bin/factory-reset-nitrokey-libremkey.sh b/initrd/bin/factory-reset-nitrokey-libremkey.sh new file mode 100755 index 000000000..6ba00f011 --- /dev/null +++ b/initrd/bin/factory-reset-nitrokey-libremkey.sh @@ -0,0 +1,232 @@ +#!/bin/sh +# +set -e -o pipefail +. /etc/functions +. /tmp/config + +mount_usb(){ +# Mount the USB boot device + if ! grep -q /media /proc/mounts ; then + mount-usb "$CONFIG_USB_BOOT_DEV" || USB_FAILED=1 + if [ $USB_FAILED -ne 0 ]; then + if [ ! -e "$CONFIG_USB_BOOT_DEV" ]; then + whiptail --title 'USB Drive Missing' \ + --msgbox "Insert your USB drive and press Enter to continue." 16 60 USB_FAILED=0 + mount-usb "$CONFIG_USB_BOOT_DEV" || USB_FAILED=1 + fi + if [ $USB_FAILED -ne 0 ]; then + whiptail $CONFIG_ERROR_BG_COLOR --title 'ERROR: Mounting /media Failed' \ + --msgbox "Unable to mount $CONFIG_USB_BOOT_DEV" 16 60 + fi + fi + fi +} + +if (whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'Factory Reset and reownership of GPG card' \ + --yesno "You are about to factory reset your GPG card!\n\nThis will:\n 1-Wipe all PRIVATE keys that were previously kept inside GPG card\n 2-Set default key size to 4096 bits (maximum)\n 3-Ask you to choose two passwords to interact with the card:\n 3.1: An administrative passphrase used to manage the card\n 3.2: A user passphrase (PIN) used everytime you sign\n encrypt/decrypt content\n4-Generate new Encryption, Signing and Authentication keys\n inside your GPG card\n5-Export associated public key, replace the one being\n present and trusted inside running BIOS, and reflash\n the SPI flash with resulting rom image.\n\nAs a result, the running BIOS will be modified. Would you like to continue?" 30 90) then + + whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'WARNING: Please Insert A USB Disk' --msgbox \ + "Please insert a USB disk on which you want to store your GPG public key\n and trustdb.\n\nThose will be backuped under the 'gpg_keys' directory.\n\nHit Enter to continue." 30 90 + + mount_usb || die "Unable to mount USB device." + #Copy generated public key, private_subkey, trustdb and artifacts to external media for backup: + mount -o remount,rw /media || die "Unable to remount /media into Read Write mode. Is the device write protected?" + + #TODO: Circumvent permission bug with mkdir and chmod permitting to use gpg --home=/media/gpg_keys directly. + #Cannot create a new gpg homedir with right permissions nor chmod 700 that directory. + #Meanwhile, we reuse /.gnupg by temporarely deleting it's existing content. + rm -rf .gnupg/* 2> /dev/null || true 2> /dev/null + killall gpg-agent gpg scdaemon 2> /dev/null || true 2> /dev/null + + if [ -z "$oem_gpg_Admin_PIN" ] || [ -z "$oem_gpg_User_PIN" ]; then + #Setting new passwords + gpgcard_user_pass1=1 + gpgcard_user_pass2=2 + gpgcard_admin_pass1=3 + gpgcard_admin_pass2=4 + else + gpgcard_user_pass1=$(echo -n "$oem_gpg_User_PIN") + gpgcard_user_pass2=$(echo -n "$oem_gpg_User_PIN") + gpgcard_admin_pass1=$(echo -n "$oem_gpg_Admin_PIN") + gpgcard_admin_pass2=$(echo -n "$oem_gpg_Admin_PIN") + fi + + while [[ "$gpgcard_user_pass1" != "$gpgcard_user_pass2" ]] || [[ ${#gpgcard_user_pass1} -lt 6 || ${#gpgcard_user_pass1} -gt 20 ]];do + { + echo -e "\nChoose your new GPG card user password (PIN) that will be typed when using GPG smartcard (Sign files, encrypt emails and files).\nIt needs to be a least 6 but not more then 20 characters:" + read -s gpgcard_user_pass1 + echo -e "\nRetype user passphrase:" + read -s gpgcard_user_pass2 + if [[ "$gpgcard_user_pass1" != "$gpgcard_user_pass2" ]]; then echo "Passwords typed were different."; fi + };done + gpgcard_user_pass=$gpgcard_user_pass1 + + while [[ "$gpgcard_admin_pass1" != "$gpgcard_admin_pass2" ]] || [[ ${#gpgcard_admin_pass1} -lt 8 || ${#gpgcard_admin_pass1} -gt 20 ]] || [ "$gpgcard_admin_pass1" != "${gpgcard_admin_pass1% *}" ]; do + { + echo -e "\nChoose your new GPG card admin password that will be typed when managing GPG smartcard (HOTP sealing, managing key, etc).\nIt needs to be a least 8 but not more then 20 characters WHILE NOT CONTAINING SPACES:" + read -s gpgcard_admin_pass1 + echo -e "\nRetype admin password:" + read -s gpgcard_admin_pass2 + + if [[ "$gpgcard_admin_pass1" != "$gpgcard_admin_pass2" ]] || [ "$gpgcard_admin_pass1" != "${gpgcard_admin_pass1% *}" ]; then echo "Passwords typed were different or contained spaces."; fi + };done + gpgcard_admin_pass=$gpgcard_admin_pass1 + + echo -e "\n\n" + echo -e "We will generate a GnuPG (GPG) keypair identifiable with the following text form:" + echo -e "Real Name (Comment) email@address.org" + + gpgcard_real_name=$(echo -n "$oem_gpg_real_name") + while [[ ${#gpgcard_real_name} -lt 5 ]]; do + { + echo -e "\nEnter your Real Name (At least 5 characters long):" + read -r gpgcard_real_name + };done + + gpgcard_email_address=$(echo -n "$oem_gpg_email") + while ! $(expr "$gpgcard_email_address" : '.*@' >/dev/null); do + { + echo -e "\nEnter your email@adress.org:" + read -r gpgcard_email_address + };done + + gpgcard_comment=$(echo -n "$oem_gpg_comment") + while [[ ${#gpgcard_comment} -gt 60 ]] || [[ -z "$gpgcard_comment" ]]; do + { + echo -e "\nEnter Comment (To distinguish this key from others with same previous attributes. Must be smaller then 60 characters):" + read -r gpgcard_comment + };done + + #Copy generated public key, private_subkey, trustdb and artifacts to external media for backup: + mount -o remount,rw /media || die "Unable to remount /media into Read Write mode. Is the device write protected?" + + #backup existing /media/gpg_keys directory + if [ -d /media/gpg_keys ];then + newdir="/media/gpg_keys-$(date '+%Y-%m-%d-%H_%M_%S')" + echo "Backing up /media/gpg_keys into $newdir" + mv /media/gpg_keys "$newdir" || die "Moving old gpg_keys directory into $newdir failed." + fi + + mkdir -p /media/gpg_keys + + #Generate Encryption, Signing and Authentication keys + whiptail --clear --title 'GPG card key generation' --msgbox \ + "BE PATIENT! Generating 4096 bits Encryption, Signing and Authentication\n keys take around 5 minutes each! Be prepared to patient around 15 minutes!\n\nHit Enter to continue" 30 90 + + confirm_gpg_card + + #Factory reset GPG card + { + echo admin + echo factory-reset + echo y + echo yes + } | gpg --command-fd=0 --status-fd=1 --pinentry-mode=loopback --card-edit --home=/.gnupg/ || die "Factory resetting the GPG card failed." + + #Setting new admin and user passwords in GPG card + { + echo admin + echo passwd + echo 1 + echo 123456 #Default user password after factory reset of card + echo "$gpgcard_user_pass" + echo "$gpgcard_user_pass" + echo 3 + echo 12345678 #Default administrator password after factory reset of card + echo "$gpgcard_admin_pass" + echo "$gpgcard_admin_pass" + echo Q + } | gpg --command-fd=0 --status-fd=2 --pinentry-mode=loopback --card-edit --home=/.gnupg/ || die "Setting new admin and user PINs in GPG card failed." + + #Set GPG card key attributes key sizes to 4096 bits + { + echo admin + echo key-attr + echo 1 # RSA + echo 4096 #Signing key size set to maximum supported by SmartCard + echo "$gpgcard_admin_pass" + echo 1 # RSA + echo 4096 #Encryption key size set to maximum supported by SmartCard + echo "$gpgcard_admin_pass" + echo 1 # RSA + echo 4096 #Authentication key size set to maximum supported by SmartCard + echo "$gpgcard_admin_pass" + } | gpg --command-fd=0 --status-fd=2 --pinentry-mode=loopback --card-edit --home=/.gnupg/ || die "Setting key attributed to RSA 4096 bits in GPG card failed." + + { + echo admin + echo generate + echo n + echo "$gpgcard_admin_pass" + echo "$gpgcard_user_pass" + echo 1y + echo "$gpgcard_real_name" + echo "$gpgcard_email_address" + echo "$gpgcard_comment" + } | gpg --command-fd=0 --status-fd=2 --pinentry-mode=loopback --card-edit --home=/.gnupg/ || die "Setting real name, e-mail address and comment in GPG failed." + + #Export and inject public key and trustdb export into extracted rom with current user keys being wiped + rom=/tmp/gpg-gui.rom + #remove invalid signsignature file + mount -o remount,rw /boot + rm -f /boot/kexec.sig + mount -o remount,ro /boot + + gpg --home=/.gnupg/ --export --armor "$gpgcard_email_address" > /media/gpg_keys/public.key || die "Exporting public key to /media/gpg_keys/public.key failed." + cp -rf /.gnupg/openpgp-revocs.d/* /media/gpg_keys/ 2> /dev/null || die "Copying revocation certificated into /media/gpg_keys/ failed." + cp -rf /.gnupg/private-keys-v1.d/* /media/gpg_keys/ 2> /dev/null || die "Copying secring exported keys to /media/gpg_keys/ failed." + cp -rf /.gnupg/pubring.* /.gnupg/trustdb.gpg /media/gpg_keys/ 2> /dev/null || die "Copying public keyring into /media/gpg_keys/ failed." + + #Flush changes to external media + mount -o remount,ro /media + + #Read rom + /bin/flash.sh -r $rom || die "Flashing back $rom including your newly genereated and exported public key failed." + + #delete previously injected public.key + if (cbfs -o $rom -l | grep -q "heads/initrd/.gnupg/keys/public.key"); then + cbfs -o $rom -d "heads/initrd/.gnupg/keys/public.key" || die "Deleting old public key from running rom backup failed." + fi + + #delete previously injected GPG1 and GPG2 pubrings + if (cbfs -o $rom -l | grep -q "heads/initrd/.gnupg/pubring.kbx"); then + cbfs -o $rom -d "heads/initrd/.gnupg/pubring.kbx" || die "Deleting old public keyring from running rom backup failed." + if (cbfs -o $rom -l | grep -q "heads/initrd/.gnupg/pubring.gpg"); then + cbfs -o $rom -d "heads/initrd/.gnupg/pubring.gpg" || die "Deleting old and deprecated public keyring from running rom backup failed." + if [ -e /.gnupg/pubring.gpg ];then + rm /.gnupg/pubring.gpg + fi + fi + fi + #delete previously injected trustdb + if (cbfs -o $rom -l | grep -q "heads/initrd/.gnupg/trustdb.gpg") then + cbfs -o $rom -d "heads/initrd/.gnupg/trustdb.gpg" || die "Deleting old trust database from running rom backup failed." + fi + #Remove old method of exporting/importing owner trust exported file + if (cbfs -o $rom -l | grep -q "heads/initrd/.gnupg/otrust.txt") then + cbfs -o $rom -d "heads/initrd/.gnupg/otrust.txt" || die "Deleting old and depracated trust database export failed." + fi + + #Insert public key in armored form and trustdb ultimately trusting user's key into reproducible rom: + cbfs -o "$rom" -a "heads/initrd/.gnupg/pubring.kbx" -f /.gnupg/pubring.kbx || die "Inserting public keyring in runnning rom backup failed." + cbfs -o "$rom" -a "heads/initrd/.gnupg/trustdb.gpg" -f /.gnupg/trustdb.gpg || die "Inserting trust databse in running rom backup failed." + + if (whiptail --title 'Flash ROM?' \ + --yesno "This will replace your old ROM with $rom\n\nDo you want to proceed?" 16 90) then + /bin/flash.sh $rom + whiptail --title 'ROM Flashed Successfully' \ + --msgbox "New $rom flashed successfully.\n\nIf your keys have changed, be sure to re-sign all files in /boot\nafter you reboot.\n\nPress Enter to continue" 16 60 + if [ -s /boot/oem ];then + mount -o remount,rw /boot + echo "gpg_factory_resetted" >> /boot/oem + mount -o remount,ro /boot + fi + mount -o remount,ro /media + else + exit 0 + fi + + whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'WARNING: Reboot required' --msgbox \ + "A reboot is required.\n\n Your firmware has been reflashed with your own public key and trust\n database included.\n\n Heads will detect the firmware change and react accordingly:\n It will ask you to reseal TOTP/HOTP (seal BIOS integrity),\n take /boot integrity measures and sign them with your freshly\n factory resetted GPG card and it's associated user password (PIN).\n\nHit Enter to reboot." 30 90 + /bin/reboot +fi diff --git a/initrd/bin/flash-gui.sh b/initrd/bin/flash-gui.sh index 3780051a1..22621e644 100755 --- a/initrd/bin/flash-gui.sh +++ b/initrd/bin/flash-gui.sh @@ -86,7 +86,7 @@ while true; do f|c ) if (whiptail --title 'Flash the BIOS with a new ROM' \ --yesno "This requires you insert a USB drive containing:\n* Your BIOS image (*.rom)\n\nAfter you select this file, this program will reflash your BIOS\n\nDo you want to proceed?" 16 90) then - mount_usb + mount_usb || die "Unable to mount USB device." if grep -q /media /proc/mounts ; then find /media -name '*.rom' > /tmp/filelist.txt file_selector "/tmp/filelist.txt" "Choose the ROM to flash" @@ -104,7 +104,7 @@ while true; do /bin/flash.sh "$ROM" fi whiptail --title 'ROM Flashed Successfully' \ - --msgbox "$ROM flashed successfully.\nPress Enter to reboot" 16 60 + --msgbox "$ROM flashed successfully. Press Enter to reboot" 16 60 umount /media /bin/reboot else diff --git a/initrd/bin/flash.sh b/initrd/bin/flash.sh index e89c9a98c..6b7ad02d2 100755 --- a/initrd/bin/flash.sh +++ b/initrd/bin/flash.sh @@ -46,6 +46,15 @@ flash_rom() { flashrom $FLASHROM_OPTIONS -w /tmp/${CONFIG_BOARD}.rom \ || die "$ROM: Flash failed" + + if [ -e /boot/kexec_key_devices.txt ] || [ -e /boot/kexec_key_lvm.txt ]; then + echo -e "\n\nBoth your TOTP/HOTP codes and TPM released Disk Unlock Key were invalidated since measured boot integrity changed." + echo -e "You will be requested to reseal TOTP/HOTP secrets, to set a new default boot option and define a new Disk Unlock Key passphrase.\n\n" + mount_boot + mount -o remount,rw /boot + touch /boot/reset_disk_unlock_key + mount -o remount,ro /boot + fi fi } diff --git a/initrd/bin/gpg-gui.sh b/initrd/bin/gpg-gui.sh index f75661075..646ffa8c9 100755 --- a/initrd/bin/gpg-gui.sh +++ b/initrd/bin/gpg-gui.sh @@ -76,6 +76,7 @@ while true; do 'a' ' Add GPG key to standalone BIOS image + flash' \ 'l' ' List GPG keys in your keyring' \ 'g' ' Generate GPG keys on a USB security token' \ + 'F' ' Factory Reset Nitrokey Pro v2/LibremKey GPG Card' \ 'x' ' Exit' \ 2>/tmp/whiptail || recovery "GUI menu failed" @@ -88,7 +89,7 @@ while true; do "a" ) if (whiptail --title 'ROM and GPG public key required' \ --yesno "This requires you insert a USB drive containing:\n* Your GPG public key (*.key or *.asc)\n* Your BIOS image (*.rom)\n\nAfter you select these files, this program will reflash your BIOS\n\nDo you want to proceed?" 16 90) then - mount_usb + mount_usb || die "Unable to mount USB device" if grep -q /media /proc/mounts ; then find /media -name '*.key' > /tmp/filelist.txt find /media -name '*.asc' >> /tmp/filelist.txt @@ -159,8 +160,8 @@ while true; do ;; "r" ) if (whiptail --title 'GPG public key required' \ - --yesno "This requires you insert a USB drive containing:\n* Your GPG public key (*.key or *.asc)\n\nAfter you select this file, this program will copy and reflash your BIOS\n\nDo you want to proceed?" 16 90) then - mount_usb + --yesno "This requires you insert a USB drive containing:\n* Your GPG public key (*.key or *.asc)\n\nNormally, the file should be named public.key\n\nAfter you select this file, this program will copy and reflash your BIOS\n\nDo you want to proceed?" 16 90) then + mount_usb || die "Unable to mount USB device" if grep -q /media /proc/mounts ; then find /media -name '*.key' > /tmp/filelist.txt find /media -name '*.asc' >> /tmp/filelist.txt @@ -238,7 +239,10 @@ while true; do echo "********************************************************************************" gpg --card-edit ;; + "F" ) + /bin/factory-reset-nitrokey-libremkey.sh + ;; esac done -exit 0 +exit 0 diff --git a/initrd/bin/gui-init b/initrd/bin/gui-init index 7a07bbea8..46863a084 100755 --- a/initrd/bin/gui-init +++ b/initrd/bin/gui-init @@ -6,12 +6,49 @@ CONFIG_BOOT_GUI_MENU_NAME='Heads Boot Menu' . /etc/functions . /tmp/config -mount_boot() -{ - # Mount local disk if it is not already mounted - if ! grep -q /boot /proc/mounts ; then - mount -o ro /boot \ - || recovery "Unable to mount /boot" +file_selector() { + FILE="" + FILE_LIST=$1 + MENU_MSG=${2:-"Choose the file"} + # create file menu options + 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" + whiptail --clear --title "Select your File" \ + --menu "${MENU_MSG} [1-$n, a to abort]:" 20 120 8 \ + -- $MENU_OPTIONS \ + 2>/tmp/whiptail || die "Aborting" + + option_index=$(cat /tmp/whiptail) + + if [ "$option_index" = "a" ]; then + option="a" + return + fi + + option=$(head -n "$option_index" "$FILE_LIST" | tail -1) + if [ "$option" == "a" ]; then + return + fi + done + if [ -n "$option" ]; then + FILE=$option + fi + else + whiptail $CONFIG_ERROR_BG_COLOR --title 'ERROR: No Files Found' \ + --msgbox "No Files found matching the pattern. Aborting." 16 60 + exit 1 fi } verify_global_hashes() @@ -62,11 +99,11 @@ verify_global_hashes() update_checksums() { if (whiptail --title 'Update Checksums and sign all files in /boot' \ - --yesno "You have chosen to update the checksums and sign all of the files in /boot.\n\nThis means that you trust that the files in /boot have not been tampered with.\n\nYou will need your GPG key to continue and this change will modify your disk.\n\nDo you want to continue?" 16 90) then + --yesno "You have chosen to update the checksums and sign all of the files in /boot.\n\nThis means that you trust that the files in /boot have not been tampered\n with.\n\nYou will need your GPG key to continue and this change will modify your\n disk.\n\nDo you want to continue?" 16 90) then mount_boot mount -o rw,remount /boot - cd /boot + cd /boot || die "Not able to change directory to /boot." find ./ -type f ! -name '*kexec*' | xargs sha256sum > /boot/kexec_hashes.txt DEFAULT_FILES=$(cat /boot/kexec_default_hashes.txt | cut -f3 -d ' ') echo $DEFAULT_FILES | xargs sha256sum > /boot/kexec_default_hashes.txt @@ -92,17 +129,243 @@ update_checksums() update_totp() { echo "Scan the QR code to add the new TOTP secret" - /bin/seal-totp + /bin/seal-totp $CONFIG_BOARD if [ -x /bin/libremkey_hotp_verification ]; then - echo "Once you have scanned the QR code, hit Enter to configure your Librem Key" + echo "Once you have scanned the QR code, hit Enter to configure your LibremKey/Nitrokey" read /bin/seal-libremkey + while [ $? -ne 0 ];do + echo -e "\n\nSealing HOTP secret into LibremKey/Nitrokey failed. Let's try again by resealing both TOTP and HOTP." + update_totp + /bin/seal-libremkey + done else echo "Once you have scanned the QR code, hit Enter to reboot" read fi /bin/reboot } +read_oem_file() +{ + echo "Mounting USB drive to provision OEM reownership from /media/oem-provisioning..." + /bin/mount-usb || warn "Unable to mount USB device. Continuing" + if [ -e /media/oem-provisioning ]; then + oem_gpg_Admin_PIN=$(grep "oem_gpg_Admin_PIN" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_gpg_Admin_PIN" ]; then + export oem_gpg_Admin_PIN="$oem_gpg_Admin_PIN" + else + unset oem_gpg_Admin_PIN + fi + + oem_gpg_User_PIN=$(grep "oem_gpg_User_PIN" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_gpg_User_PIN" ]; then + export oem_gpg_User_PIN="$oem_gpg_User_PIN" + else + unset oem_gpg_User_PIN + fi + + oem_gpg_real_name=$(grep "oem_gpg_real_name" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_gpg_real_name" ]; then + export oem_gpg_real_name="$oem_gpg_real_name" + else + unset oem_gpg_real_name + fi + + oem_gpg_email=$(grep "oem_gpg_email" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_gpg_email" ]; then + export oem_gpg_email="$oem_gpg_email" + else + unset oem_gpg_email + fi + + oem_gpg_comment=$(grep "oem_gpg_comment" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_gpg_comment" ]; then + export oem_gpg_comment="$oem_gpg_comment" + else + unset oem_gpg_comment + fi + + oem_luks_actual_Disk_Recovery_Key=$(grep "oem_luks_actual_Disk_Recovery_Key" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_luks_actual_Disk_Recovery_Key" ]; then + export oem_luks_actual_Disk_Recovery_Key="$oem_luks_actual_Disk_Recovery_Key" + else + unset oem_luks_actual_Disk_Recovery_Key + fi + + oem_luks_new_Disk_Recovery_Key=$(grep "oem_luks_new_Disk_Recovery_Key" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_luks_new_Disk_Recovery_Key" ]; then + export oem_luks_new_Disk_Recovery_Key="$oem_luks_new_Disk_Recovery_Key" + else + unset oem_luks_new_Disk_Recovery_Key + fi + + oem_luks_Disk_Unlock_Key=$(grep "oem_luks_Disk_Unlock_Key" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_luks_Disk_Unlock_Key" ]; then + export oem_luks_Disk_Unlock_Key="$oem_luks_Disk_Unlock_Key" + else + unset oem_luks_Disk_Unlock_Key + fi + + oem_TPM_Owner_Password=$(grep "oem_TPM_Owner_Password" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_TPM_Owner_Password" ]; then + export oem_TPM_Owner_Password="$oem_TPM_Owner_Password" + else + unset oem_TPM_Owner_Password + fi + + export oem_configuration_read=1 + fi +} +check_onboarding_progress() +{ + mount_boot + if [ -e /boot/oem ]; then + res=$(grep onboarding /boot/oem 2>&1 > /dev/null) + if [ $? -ne 0 ];then + #Show Onboarding menu once. + whiptail --title 'Hardware reownership Wizard' --msgbox \ + "The received hardware is currently owned by $oem_name.\nWe will change that.\n\nThis Wizard will otherwise make you own your own hardware by:\n1-Reencrypting encrypted drive content (LUKS container)\n2-Changing LUKS Disk Recovery Key and it's passphrase\n3-Resetting your LibremKey/Nitrokey Pro v2 to factory defaults\n4-Setting User and Admin PINs into your LibremKey/NitroKey\n4-Generating keys in it, exporting public key and\n importing it in the rom prior to reprogramming the SPI flash with it\n6-Taking integrity measures of all /boot files and sign the resulting\n checksum file with yourLibremKey/Nitrokey Pro\n6-Owning your Trusted Platform Module (TPM)\n\nScan the QR Code with an OTP app only after Reset the TPM last phase.\n\nHit Enter to continue." 20 20 + whiptail --title 'Hardware reownership Wizard' --msgbox \ + "On the next screen, MAKE SURE THAT THE HOTP CODE IS: 'Success'\n\nIf it's not, reboot your hardware with your Librem/Nitrokey inserted.\n\nIf the HOTP code is still invalid, your hardware may been tampered with in\ntransit. Contact $oem_name." 20 20 + totp_confirm="O" + echo $totp_confirm > /tmp/whiptail + mount -o remount,rw /boot + echo "onboarding" >> /boot/oem + mount -o remount,ro /boot + fi + res=$(grep luks_reencrypted /boot/oem 2>&1 > /dev/null) + if [ $? -ne 0 ];then + export reownership_state="luks_reencryption" + totp_confirm="R" + echo $totp_confirm > /tmp/whiptail + return + fi + res=$(grep luks_passwd_changed /boot/oem 2>&1 > /dev/null) + if [ $? -ne 0 ];then + export reownership_state="luks_password_change" + totp_confirm="R" + return + fi + res=$(grep gpg_factory_resetted /boot/oem 2>&1 > /dev/null) + if [ $? -ne 0 ];then + /bin/factory-reset-nitrokey-libremkey.sh + return + fi + res=$(grep tpm_reowned /boot/oem 2>&1 > /dev/null) + if [ $? -ne 0 ];then + totp_confirm="p" + echo $totp_confirm > /tmp/whiptail + return + fi + if [ $(grep -E "luks_reencrypted|luks_passwd_changed|gpg_factory_resetted|tpm_reowned" /boot/oem | uniq | wc -l) -eq 4 ];then + if [ $HOTP = "Success" ];then + mount -o remount,rw /boot + rm /boot/oem + mount -o remount,ro /boot + unset totp_confirm + unset reownership_state + whiptail --title 'DISK UNLOCK KEY ADVICE 1/3' --msgbox \ + "***You SHOULD SET a new Disk Unlock Key for your own data privacy!!!***\n\nDoing so, a witness will only be able to type observed Disk Unlock\n Key passphrase from this computer and won't be able on a cloned\n copy of this disk.\n\nThe release of Disk Unlock Key happens ONLY if TPM attests firmware\nintegrity, and only if Disk Unlock Key passphrase is valid.\n\nPlease hit Enter to continue" 30 60 + + whiptail --title 'DISK UNLOCK KEY ADVICE 2/3' --msgbox \ + "Otherwise, typing your Disk Recovery Key passphrase at boot puts you\nat risk. Someone could clone your disk and type that witnessed\npassphrase and access your data both locally and from a cloned\ndisk.\n\nCoupled with a strong passphrase, this improves your data privacy.\nCONSIDER YOURSELF WARNED.\n\nPlease hit Enter to continue" 30 60 + + whiptail --title 'DISK UNLOCK KEY ADVICE 3/3' --msgbox \ + "To set Disk Unlock Key, released by the TPM only if firmware integrity\n is attested:\n\nSelect from Main menu:\n\nAdvanced Options menu -> Other Boot Options -> Show OS boot menu\n1-Then select the first boot option proposed (dynamic option)\n2-Then,answer Y when asked to add Disk Unlock Key to the TPM.\n\nYou will be prompted to set one in the following steps.\n\nPlease hit Enter to continue" 30 60 + return + else + #Deal with corner case where after inserting key in previous step, HOTP seal fails with provided good password. + #In that case, we regenerate HOTP and TOTP + totp_confirm="g" + echo $totp_confirm > /tmp/whiptail + fi + fi + else + reset_disk_unlock_key + return + fi +} +reset_disk_unlock_key() +{ + mount_boot + + if [ "$CONFIG_TPM" = n ]; then + TOTP="NO TPM" + else + TOTP=`unseal-totp` + if [ $? -ne 0 ]; then + echo "Error generating TOTP code. We will regenerate it now." + update_totp + continue + elif [ -x /bin/libremkey_hotp_verification ]; then + HOTP=`unseal-hotp` + enable_usb + if ! libremkey_hotp_verification info ; then + whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'WARNING: Please Insert Your LibremKey/Nitrokey' --msgbox "Your LibremKey/Nitrokey was not detected.\n\nPlease insert your LibremKey/Nitrokey" 30 90 + fi + # Don't output HOTP codes to screen, so as to make replay attacks harder + libremkey_hotp_verification check "$HOTP" + case "$?" in + 0 ) + HOTP="Success" + ;; + 4 ) + HOTP="Invalid code" + MAIN_MENU_BG_COLOR=$CONFIG_ERROR_BG_COLOR + ;; + * ) + HOTP="Error checking code, Insert LibremKey/Nitrokey and retry" + MAIN_MENU_BG_COLOR=$CONFIG_WARNING_BG_COLOR + ;; + esac + else + HOTP='N/A' + fi + + if [ $HOTP = "Success" ];then + mount -o remount,rw /boot + rm /boot/reset_disk_unlock_key + mount -o remount,ro /boot + verify_global_hashes + kexec-select-boot -m -b /boot -c "grub.cfg" -g + continue + else + echo -e "HOTP status: $HOTP\n\nHit Enter to regenerate new TOTP/HOTP codes." + read + update_totp + fi + continue + fi +} + +mount_boot +if [ -e /boot/oem ];then + if [ -z "$oem_configuration_read" ]; then + #Read /media/oem-provisioning file once to read provisioned secrets + read_oem_file + + oem_name=$(grep "oem_name" /boot/oem | awk -F '=' {'print $2'}) + if [ -n "$oem_name" ]; then + export oem_name="$oem_name" + else + oem_name="your OEM" + export oem_name="$oem_name" + fi + fi +fi + + +#TODO:validate that resetting disk unlock key only happens when /boot/oem doesn't exist anymore. Should happen after TPM reset. +#Flashing modifies measurements, which should trigger TOTP/HOTP resealing. That happens when inserting gpg public key. +#Measurements become invalid when TPM is reset, also. +if [ -e /boot/reset_disk_unlock_key ] && [ ! -e /boot/oem ]; then + if (whiptail $CONFIG_WARNING_BG_COLOR --title "WARNING: You must change your Disk Unlock Key" \ + --yesno "You just updated the ROM, which requires resealing TOTP/HOTP secrets.\nTPM released Disk Unlock Key stored in LUKS header must also be regenerated.\n\nIf you did not modify the ROM, this might be a sign of system compromise.\nIn that case, you should say No here and investigate." 30 90) then + reset_disk_unlock_key + else + recovery "User refused to update TOTP/HOTP following what seemed to be a ROM update. Time to investigate changes manually." + fi +fi last_half=X while true; do @@ -121,6 +384,7 @@ while true; do totp_confirm=$(cat /tmp/whiptail) fi + if [ "$totp_confirm" = "i" -o -z "$totp_confirm" ]; then # update the TOTP code every thirty seconds date=`date "+%Y-%m-%d %H:%M:%S"` @@ -132,13 +396,14 @@ while true; do last_half=$half; TOTP=`unseal-totp` if [ $? -ne 0 ]; then + #Normal path. We give user a choice. whiptail $CONFIG_ERROR_BG_COLOR --clear --title "ERROR: TOTP Generation Failed!" \ --menu "ERROR: Heads couldn't generate the TOTP code.\n\nIf this is the first time the system has booted, you should reset the TPM\nand set your own password\n\nIf you just reflashed your BIOS, you'll need to generate a new TOTP secret.\n\nIf you have not just reflashed your BIOS, THIS COULD INDICATE TAMPERING!\n\nHow would you like to proceed?" 30 90 4 \ 'g' ' Generate new TOTP/HOTP secret' \ 'i' ' Ignore error and continue to default boot menu' \ 'p' ' Reset the TPM' \ 'x' ' Exit to recovery shell' \ - 2>/tmp/whiptail || recovery "GUI menu failed" + 2>/tmp/whiptail || recovery "GUI menu failed" totp_confirm=$(cat /tmp/whiptail) fi @@ -150,10 +415,10 @@ while true; do HOTP=`unseal-hotp` enable_usb if ! libremkey_hotp_verification info ; then - whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'WARNING: Please Insert Your Librem Key' --msgbox "Your Librem Key was not detected.\n\nPlease insert your Librem Key" 30 90 + whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'WARNING: Please Insert Your LibremKey/Nitrokey' --msgbox "Your LibremKey/Nitrokey was not detected.\n\nPlease insert your LibremKey/Nitrokey" 30 90 fi # Don't output HOTP codes to screen, so as to make replay attacks harder - libremkey_hotp_verification check $HOTP + libremkey_hotp_verification check "$HOTP" case "$?" in 0 ) HOTP="Success" @@ -163,7 +428,7 @@ while true; do MAIN_MENU_BG_COLOR=$CONFIG_ERROR_BG_COLOR ;; * ) - HOTP="Error checking code, Insert Librem Key and retry" + HOTP="Error checking code, Insert LibremKey/Nitrokey and retry" MAIN_MENU_BG_COLOR=$CONFIG_WARNING_BG_COLOR ;; esac @@ -171,14 +436,32 @@ while true; do HOTP='N/A' fi - whiptail $MAIN_MENU_BG_COLOR --clear --title "$CONFIG_BOOT_GUI_MENU_NAME" \ - --menu "$date\nTOTP: $TOTP | HOTP: $HOTP" 20 90 10 \ - 'y' ' Default boot' \ - 'a' ' Advanced Settings -->' \ - 'x' ' Exit to recovery shell' \ - 2>/tmp/whiptail || recovery "GUI menu failed" + if [ -e /boot/oem ]; then + check_onboarding_progress + totp_confirm="O" + echo $totp_confirm > /tmp/whiptail + else + whiptail $MAIN_MENU_BG_COLOR --clear --title "$CONFIG_BOOT_GUI_MENU_NAME" \ + --menu "Greenwich Mean Time (GMT) : $date\nTOTP: $TOTP | HOTP: $HOTP" 20 90 10 \ + 'y' ' Default boot' \ + 'a' ' Advanced Settings -->' \ + 'x' ' Exit to recovery shell' \ + 2>/tmp/whiptail || recovery "GUI menu failed" + totp_confirm=$(cat /tmp/whiptail) + fi + fi - totp_confirm=$(cat /tmp/whiptail) + if [ "$totp_confirm" = "O" ]; then + whiptail $MAIN_MENU_BG_COLOR --clear --title "$CONFIG_BOOT_GUI_MENU_NAME: Reownership" \ + --menu "Greenwich Mean Time (GMT) : $date\nTOTP: $TOTP | HOTP: $HOTP" 20 90 10 \ + 'C' ' Continue ownership of devices' \ + 'x' ' Exit to recovery shell' \ + 2>/tmp/whiptail || recovery "GUI menu failed" + totp_confirm=$(cat /tmp/whiptail) + fi + + if [ "$totp_confirm" = "C" ]; then + check_onboarding_progress fi if [ "$totp_confirm" = "a" ]; then @@ -186,10 +469,11 @@ while true; do --menu "Configure Advanced Settings" 20 90 10 \ 'o' ' Other Boot Options -->' \ 't' ' TPM/TOTP/HOTP Options -->' \ - 's' ' Update checksums and sign all files in /boot' \ - 'c' ' Change configuration settings -->' \ - 'f' ' Flash/Update the BIOS -->' \ 'G' ' GPG Options -->' \ + 'f' ' Flash/Update the BIOS -->' \ + 'c' ' Change configuration settings -->' \ + 's' ' Update checksums and sign all files in /boot' \ + 'R' ' Reencrypt LUKS container' \ 'r' ' <-- Return to main menu' \ 2>/tmp/whiptail || recovery "GUI menu failed" @@ -260,8 +544,16 @@ while true; do if [ "$totp_confirm" = "p" ]; then if (whiptail --title 'Reset the TPM' \ - --yesno "This will clear the TPM and TPM password, replace them with new ones!\n\nDo you want to proceed?" 16 90) then + --yesno "This will clear the TPM content and reset TPM Owner password.\n\nDo you want to proceed?" 16 90) then /bin/tpm-reset + + #set flag in oem file + mount_boot + if [ -s /boot/oem ];then + mount -o remount,rw /boot + echo "tpm_reowned" >> /boot/oem + mount -o remount,ro /boot + fi # now that the TPM is reset, remove invalid TPM counter files mount_boot @@ -330,6 +622,11 @@ while true; do continue fi + if [ "$totp_confirm" = "R" ]; then + /bin/reencrypt-luks + continue + fi + if [ "$totp_confirm" = "y" -o -n "$totp_confirm" ]; then # Try to boot the default mount_boot diff --git a/initrd/bin/kexec-insert-key b/initrd/bin/kexec-insert-key index 5b4020ecd..dde229d40 100755 --- a/initrd/bin/kexec-insert-key +++ b/initrd/bin/kexec-insert-key @@ -1,5 +1,5 @@ #!/bin/sh -# Unseal a disk key from TPM and add to a new initramfs +# Unseal a Disk Unlock Key from TPM and add to a new initramfs set -e -o pipefail . /etc/functions @@ -23,10 +23,10 @@ if [ -r "$TMP_KEY_LVM" ]; then die "No LVM volume group defined for activation" fi lvm vgchange -a y $VOLUME_GROUP \ - || die "$VOLUME_GROUP: unable to activate volume group" + || die "$VOLUME_GROUP: Unable to activate volume group" fi -# Measure the LUKS headers before we unseal the disk key +# Measure the LUKS headers before we unseal the Disk Unock Key cat "$TMP_KEY_DEVICES" | cut -d\ -f1 | xargs /bin/qubes-measure-luks \ || die "LUKS measure failed" @@ -37,12 +37,12 @@ INITRD_DIR=/tmp/secret/initrd SECRET_CPIO=/tmp/secret/initrd.cpio mkdir -p "$INITRD_DIR/etc" -# Attempt to unseal the disk key from the TPM +# Attempt to unseal the Disk Unlock Key from the TPM # should we give this some number of tries? unseal_failed="n" if ! kexec-unseal-key "$INITRD_DIR/secret.key" ; then unseal_failed="y" - echo "!!! Failed to unseal the TPM LUKS disk key" + echo "!!! Failed to unseal the TPM LUKS Disk Unlock Key" fi # Override PCR 4 so that user can't read the key @@ -54,14 +54,14 @@ if [ "$unseal_failed" = "y" ]; then confirm_boot="n" read \ -n 1 \ - -p "Do you wish to boot and use the disk recovery key? [Y/n] " \ + -p "Do you wish to boot and use the Disk Recovery Key? [Y/n] " \ confirm_boot if [ "$confirm_boot" != 'y' \ -a "$confirm_boot" != 'Y' \ -a -n "$confirm_boot" ] \ ; then - die "!!! Aborting boot due to failure to unseal TPM disk key" + die "!!! Aborting boot due to failure to unseal TPM Disk Unlock Key" fi fi diff --git a/initrd/bin/kexec-save-default b/initrd/bin/kexec-save-default index 85ac3f27e..c3283f611 100755 --- a/initrd/bin/kexec-save-default +++ b/initrd/bin/kexec-save-default @@ -5,24 +5,24 @@ set -e -o pipefail . /etc/functions while getopts "b:d:p:i:" arg; do - case $arg in - b) bootdir="$OPTARG" ;; - d) paramsdev="$OPTARG" ;; - p) paramsdir="$OPTARG" ;; - i) index="$OPTARG" ;; - esac + case $arg in + b) bootdir="$OPTARG" ;; + d) paramsdev="$OPTARG" ;; + p) paramsdir="$OPTARG" ;; + i) index="$OPTARG" ;; + esac done if [ -z "$bootdir" -o -z "$index" ]; then - die "Usage: $0 -b /boot -i menu_option " + die "Usage: $0 -b /boot -i menu_option " fi if [ -z "$paramsdev" ]; then - paramsdev="$bootdir" + paramsdev="$bootdir" fi if [ -z "$paramsdir" ]; then - paramsdir="$bootdir" + paramsdir="$bootdir" fi bootdir="${bootdir%%/}" @@ -33,106 +33,213 @@ TMP_MENU_FILE="/tmp/kexec/kexec_menu.txt" ENTRY_FILE="$paramsdir/kexec_default.$index.txt" HASH_FILE="$paramsdir/kexec_default_hashes.txt" + +lvm_suggest=$(lvm vgscan|awk -F '"' {'print $1'}|tail -n +2) +num_lvm=$(echo "$lvm_suggest"|wc -l) +if [ "$num_lvm" -eq 1 ] && [ -n "$lvm_suggest" ]; then + lvm_volume_group=$lvm_suggest +elif [ -z "$lvm_suggest" ]; then + num_lvm=0 +fi + +devices_suggest=$(blkid | cut -d ':' -f 1 | while read device;do cryptsetup isLuks "$device";if [ $(echo $?) == 0 ]; then echo "$device";fi; done | sort) +num_devices=$(echo "$devices_suggest"|wc -l) +if [ "$num_devices" -eq 1 ]; then + key_devices=$devices_suggest +else + devices_suggest=$(echo $devices_suggest) +fi + + if [ ! -r "$TMP_MENU_FILE" ]; then - die "No menu options available, please run kexec-select-boot" + die "No menu options available, please run kexec-select-boot" fi -entry=`head -n $index $TMP_MENU_FILE | tail -1` +entry=$(head -n "$index" $TMP_MENU_FILE | tail -1) if [ -z "$entry" ]; then - die "Invalid menu index $index" + die "Invalid menu index $index" fi KEY_DEVICES="$paramsdir/kexec_key_devices.txt" KEY_LVM="$paramsdir/kexec_key_lvm.txt" save_key="n" + if [ "$CONFIG_TPM" = "y" ]; then - if [ ! -r "$KEY_DEVICES" ]; then - read \ - -n 1 \ - -p "Do you wish to add a disk encryption to the TPM [y/N]: " \ - add_key_confirm - echo - - if [ "$add_key_confirm" = "y" \ - -o "$add_key_confirm" = "Y" ]; then - lvm_suggest="e.g. qubes_dom0 or blank" - devices_suggest="e.g. /dev/sda2 or blank" - save_key="y" - fi - else - read \ - -n 1 \ - -p "Do you want to reseal a disk key to the TPM [y/N]: " \ - change_key_confirm - echo - - if [ "$change_key_confirm" = "y" \ - -o "$change_key_confirm" = "Y" ]; then - old_lvm_volume_group="" - if [ -r "$KEY_LVM" ]; then - old_lvm_volume_group=`cat $KEY_LVM` || true - old_key_devices=`cat $KEY_DEVICES \ - | cut -d\ -f1 \ - | grep -v "$old_lvm_volume_group" \ - | xargs` || true - else - old_key_devices=`cat $KEY_DEVICES \ - | cut -d\ -f1 | xargs` || true - fi - - lvm_suggest="was '$old_lvm_volume_group'" - devices_suggest="was '$old_key_devices'" - save_key="y" - fi - fi - - if [ "$save_key" = "y" ]; then - echo "+++ LVM volume groups (lvm vgscan): " - lvm vgscan || true - - read \ - -p "Encrypted LVM group? ($lvm_suggest): " \ - lvm_volume_group - - echo "+++ Block devices (blkid): " - blkid || true - - read \ - -p "Encrypted devices? ($devices_suggest): " \ - key_devices - - save_key_params="-s -p $paramsdev" - if [ -n "$lvm_volume_group" ]; then - save_key_params="$save_key_params -l $lvm_volume_group $key_devices" - else - save_key_params="$save_key_params $key_devices" - fi - echo "Running kexec-save-key with params: $save_key_params" - kexec-save-key $save_key_params \ - || die "Failed to save the disk key" - fi + if [ ! -s "$KEY_DEVICES" ]; then + read \ + -n 1 \ + -p "Do you wish to add a Disk Unlock Key to the TPM [Y/n]: " \ + add_key_confirm + echo + + if [ "$add_key_confirm" = "y" ] || [ "$add_key_confirm" = "Y" ] || [ -z "$add_key_confirm" ]; then + if [ "$num_lvm" -gt 1 ]; then + //untested + selected_lvmdev_not_existing=1 + while [ $selected_lvmdev_not_existing -ne 0 ];do + { + read \ + -p "Encrypted LVM group? choose between: $lvm_suggest: " \ + lvm_volume_group + + result=$(echo "$lvm_suggest" | grep -q "$lvm_volume_group") || selected_lvmdev_not_existing=1 + if [ $? == 0 ]; then + selected_lvmdev_not_existing=0 + fi + };done + elif [ "$num_lvm" -eq 1 ]; then + echo "Single Encrypted LVM group found at $lvm_suggest. Using it." + lvm_volume_group=$lvm_suggest + else + echo "No encrypted LVM Group found." + fi + + if [ "$num_devices" -gt 1 ]; then + selected_luksdev_not_existing=1 + while [ $selected_luksdev_not_existing -ne 0 ];do + { + read \ + -p "Encrypted devices? (choose between: $devices_suggest): " \ + key_devices + + result=$(echo "$devices_suggest" | grep -q "$key_devices") || selected_luksdev_not_existing=1 + if [ $? == 0 ]; then + selected_luksdev_not_existing=0 + fi + };done + elif [ "$num_devices" -eq 1 ]; then + echo "Single Encrypted Disk found at $devices_suggest. Using it." + key_devices=$devices_suggest + else + echo "No encrypted devices found." + fi + + save_key="y" + else + die "User chose to not add Disk Unlock Key to the TPM" + fi + else + read \ + -n 1 \ + -p "Do you want to reseal a Disk Unlock Key to the TPM [Y/n]: " \ + change_key_confirm + echo + + if [ "$change_key_confirm" = "y" ] || [ "$change_key_confirm" = "Y" ] || [ -z "$change_key_confirm" ]; then + old_lvm_volume_group="" + if [ -r "$KEY_LVM" ]; then + old_lvm_volume_group=$(cat "$KEY_LVM") || true + old_key_devices=$(cat "$KEY_DEVICES" \ + | cut -d\ -f1 \ + | grep -v "$old_lvm_volume_group" \ + | xargs) || true + else + old_key_devices=$(cat "$KEY_DEVICES" \ + | cut -d\ -f1 | xargs) || true + fi + + lvm_suggest="$old_lvm_volume_group" + devices_suggest="$old_key_devices" + save_key="y" + else + echo -e "\n\nTo set a new Disk Unlock Key passphrase, different then Disk Recovery Key passphrase, resealing the Disk Unlock key to the TPM is needed.\n\nThe actual default boot option have been invalidated by a firmware upgrade or a firmware tampering.\nIf you are the origin of the change, you have already resealed TOTP/HOTP, prompted from TPM measurements mismatches.\n\nIt is strongly advised to set a new default boot option, which will add the Disk Unlock Key to the TPM.\n\nThe Disk Unlock Key passphrase you will choose at this step will be required of you at each machine startup and will protect the Disk Recovery Key passphrase from interested eyes.\n\nBy selecting a Disk Unlock Key passphrase, a camera that would see you type your Disk Unlock Key passphrase will only be able to access the content of your hard drive on this computer.\n\nMore critically, someone knowing your Disk Recovery Key passphrase would just have to clone your disk (which takes 30 minutes) and be able to access its content from any other computer later on.\nConsider yourself warned.\n" + die "User refused to reseal the Disk Unlock Key to the TPM" + fi + fi + + if [ "$save_key" = "y" ]; then + if [ -n "$old_key_devices" ] || [ -n "$old_lvm_volume_group" ]; then + read \ + -n 1 \ + -p "Do you want to reuse configured Encrypted LVM groups/Block devices? (Y/n):" \ + reuse_past_devices + echo + if [ "$reuse_past_devices" = "y" ] || [ "$reuse_past_devices" = "Y" ] || [ -z "$reuse_past_devices" ]; then + if [ -z "$key_devices" ] && [ -n "$old_key_devices" ]; then + key_devices="$old_key_devices" + fi + if [ -z "$lvm_volume_group" ] && [ -n "$old_lvm_volume_group" ]; then + lvm_volume_group="$old_lvm_volume_group" + fi + else + if [ "$num_lvm" -eq 1 ]; then + echo "Single Encrypted LVM group found at $lvm_suggest. Using it." + lvm_volume_group="$lvm_suggest" + elif [ "$num_lvm" -gt 1 ]; then + //untested + selected_lvmdev_not_existing=1 + while [ $selected_lvmdev_not_existing -ne 0 ];do + { + read \ + -p "Encrypted LVM group? (choose between: $lvm_suggest): " \ + lvm_volume_group + + result=$(echo "$lvm_suggest" | grep -q "$lvm_volume_group") || selected_lvmdev_not_existing=1 + if [ $? == 0 ]; then + selected_lvmdev_not_existing=0 + fi + };done + else + echo "No encrypted LVM Group found." + fi + + if [ "$num_devices" -eq 1 ]; then + echo "Single Encrypted Disk found at $devices_suggest. Using it." + key_devices="$devices_suggest" + elif [ "$num_devices" -gt 1 ]; then + selected_luksdev_not_existing=1 + while [ $selected_luksdev_not_existing -ne 0 ];do + { + read \ + -p "Encrypted devices? (choose between: $devices_suggest): " \ + key_devices + + result=$(echo "$devices_suggest" | grep -q "$key_devices") || selected_luksdev_not_existing=1 + if [ $? == 0 ]; then + selected_luksdev_not_existing=0 + fi + };done + else + echo "No encrypted devices found." + fi + fi + fi + + save_key_params="-s -p $paramsdev" + if [ -n "$lvm_volume_group" ]; then + save_key_params="$save_key_params -l $lvm_volume_group $key_devices" + elif [ -n "$key_devices" ]; then + save_key_params="$save_key_params $key_devices" + else + die "No LVM Group nor encrypted devices provided." + fi + fi + + echo -e "\nRunning kexec-save-key with params: $save_key_params\n" + kexec-save-key $save_key_params \ + || die "Failed to save the Disk Unlock Key" fi # try to switch to rw mode mount -o rw,remount $paramsdev if [ ! -d $paramsdir ]; then - mkdir -p $paramsdir \ - || die "Failed to create params directory" + mkdir -p $paramsdir \ + || die "Failed to create params directory" fi rm "$paramsdir/kexec_default.*.txt" 2>/dev/null || true echo "$entry" > $ENTRY_FILE cd $bootdir && kexec-boot -b "$bootdir" -e "$entry" -f | \ - xargs sha256sum > $HASH_FILE \ + xargs sha256sum > $HASH_FILE \ || die "Failed to create hashes of boot files" if [ ! -r $ENTRY_FILE -o ! -r $HASH_FILE ]; then - die "Failed to write default config" + die "Failed to write default config" fi # sign and auto-roll config counter extparam= if [ "$CONFIG_TPM" = "y" ]; then - extparam=-u + extparam=-u fi kexec-sign-config -p $paramsdir $extparam \ || die "Failed to sign default config" diff --git a/initrd/bin/kexec-save-key b/initrd/bin/kexec-save-key index 2ea17f637..01219fcb6 100755 --- a/initrd/bin/kexec-save-key +++ b/initrd/bin/kexec-save-key @@ -1,5 +1,5 @@ #!/bin/sh -# Generate a TPM key used to unlock LUKS disks +# Generate a TPM Disk Unlock Key used to unlock LUKS disks set -e -o pipefail . /etc/functions diff --git a/initrd/bin/kexec-seal-key b/initrd/bin/kexec-seal-key index 46980af8e..4243ec7ba 100755 --- a/initrd/bin/kexec-seal-key +++ b/initrd/bin/kexec-seal-key @@ -1,5 +1,5 @@ #!/bin/sh -# This will generate a disk encryption key and seal / ecncrypt +# This will generate a Disk Unlock Key and seal / encrypt # with the current PCRs and then store it in the TPM NVRAM. # It will then need to be bundled into initrd that is booted. set -e -o pipefail @@ -32,23 +32,37 @@ if [ -r "$KEY_LVM" ]; then die "No LVM volume group defined for activation" fi lvm vgchange -a y $VOLUME_GROUP \ - || die "$VOLUME_GROUP: unable to activate volume group" + || die "$VOLUME_GROUP: Unable to activate volume group" fi -# Key slot 0 is the manual recovery pass phrase -# that they user entered when they installed Qubes, -# key slot 1 is the one that we've generated. -read -s -p "Enter disk recovery key: " disk_password -echo -n "$disk_password" > "$RECOVERY_KEY" -echo - -read -s -p "New disk unlock password for booting: " key_password -echo -read -s -p "Repeat unlock code: " key_password2 -echo +# Key slot 0 is the Disk Recovery Key pass phrase +# that the user/OEM entered when they installed/reencrypted the Operating System (LUKS container) +# key slot 1 is the Disk Unlock Key that the user generated. +if [ -z "$oem_luks_new_Disk_Recovery_Key" ]; then + read -s -p "Enter Disk Recovery Key passphrase: " disk_password + echo -n "$disk_password" > "$RECOVERY_KEY" + echo +else + echo -n "$oem_luks_new_Disk_Recovery_Key" > "$RECOVERY_KEY" +fi -if [ "$key_password" != "$key_password2" ]; then - die "Key passwords do not match" +if [ -z "$oem_luks_Disk_Unlock_Key" ]; then + password_mismatch=1 + while [ "$password_mismatch" -ne 0 ];do + { + read -s -p "New Disk Unlock Key passphrase for booting Operating System: " key_password + echo + read -s -p "Repeat Disk Unlock Key passphrase: " key_password2 + echo + + if [ "$key_password" != "$key_password2" ]; then + echo "Disk Unlock Key passphrases did not match" + else + password_mismatch=0 + fi + };done +else + key_password=$(echo -n "$oem_luks_Disk_Unlock_Key") fi # Generate key file @@ -62,18 +76,18 @@ dd \ # Remove all the old keys from slot 1 for dev in `cat "$KEY_DEVICES" | cut -d\ -f1`; do - echo "++++++ $dev: Removing old key slot" - cryptsetup luksKillSlot \ - --key-file "$RECOVERY_KEY" \ - $dev 1 \ - || warn "$dev: ignoring problem" - - echo "++++++ $dev: Adding key" - cryptsetup luksAddKey \ - --key-file "$RECOVERY_KEY" \ - --key-slot 1 \ - $dev "$KEY_FILE" \ - || die "$dev: Unable to add key" + echo "++++++ $dev: Removing key slot 1" + cryptsetup luksKillSlot \ + --key-file "$RECOVERY_KEY" \ + $dev 1 \ + || warn "Removing LUKS Disk Unlock Key on $dev (key slot 1) failed. Bad passphrase or key slot 1 not existing. Continuing..." + + echo "++++++ $dev: Adding key" + cryptsetup luksAddKey \ + --key-file "$RECOVERY_KEY" \ + --key-slot 1 \ + $dev "$KEY_FILE" \ + || die "Unable to add key to $dev key slot 1. Please try again with actual LUKS Disk Recovery Key Password." done # Now that we have setup the new keys, measure the PCRs @@ -84,8 +98,8 @@ cat "$KEY_DEVICES" | cut -d\ -f1 | xargs /bin/qubes-measure-luks \ || die "Unable to measure the LUKS headers" luks_pcr=`tpm calcfuturepcr -ix 16 -if /tmp/luksDump.txt` -# Librem Key loads USB modules which changes PCR5. -# In the event Librem Key is enabled, skip verification of PCR5 +# LibremKey/Nitrokey loads USB modules which changes PCR5. +# In the event LibremKey/Nitrokey is enabled, skip verification of PCR5 if [ -x /bin/libremkey_hotp_verification ]; then pcr_5="X" else @@ -132,9 +146,13 @@ if ! tpm nv_writevalue \ # about the sealed file tpm physicalpresence -s \ || warn "Warning: Unable to assert physical presence" - - read -s -p "TPM Owner password: " tpm_password - echo + + if [ -z "$oem_TPM_Owner_Password" ]; then + read -s -p "TPM Owner password: " tpm_password + echo + else + tpm_password=$(echo -n "$oem_TPM_Owner_Password") + fi tpm nv_definespace \ -in $TPM_INDEX \ diff --git a/initrd/bin/kexec-select-boot b/initrd/bin/kexec-select-boot index ab8002fef..93c270328 100755 --- a/initrd/bin/kexec-select-boot +++ b/initrd/bin/kexec-select-boot @@ -135,7 +135,7 @@ confirm_menu_option() { if [ "$gui_menu" = "y" ]; then whiptail --clear --title "Confirm boot details" \ --menu "Confirm the boot details for $name:\n\n$option\n\n" 20 120 8 \ - -- 'y' "Boot $name" 'd' "Make $name the default" \ + -- 'd' "Make $name the default" 'y' "Boot $name" \ 2>/tmp/whiptail || die "Aborting boot attempt" option_confirm=$(cat /tmp/whiptail) @@ -176,11 +176,11 @@ scan_options() { save_default_option() { read \ -n 1 \ - -p "Saving a default will modify the disk. Proceed? (y/n): " \ + -p "Saving a default will modify the disk. Proceed? (Y/n): " \ default_confirm echo - if [ "$default_confirm" = "y" ]; then + if [ "$default_confirm" = "y" ] || [ "$default_confirm" = "Y" ] || [ -z "$default_confirm" ]; then if kexec-save-default \ -b "$bootdir" \ -d "$paramsdev" \ @@ -191,9 +191,16 @@ save_default_option() { sleep 2 default_failed="n" force_menu="n" + if [ -e /boot/reset_disk_unlock_key ]; then + mount -o remount,rw /boot + rm -f /boot/reset_disk_unlock_key + mount -o remount,ro /boot + fi return else echo "Failed to save defaults" + echo "Press Enter to continue" + read fi fi diff --git a/initrd/bin/kexec-sign-config b/initrd/bin/kexec-sign-config index 23cdf28d9..50db5749f 100755 --- a/initrd/bin/kexec-sign-config +++ b/initrd/bin/kexec-sign-config @@ -48,17 +48,39 @@ if [ -z "$param_files" ]; then die "$paramsdir: No kexec parameter files to sign" fi -for tries in 1 2 3; do - if sha256sum $param_files | gpg \ - --digest-algo SHA256 \ - --detach-sign \ - -a \ - > $paramsdir/kexec.sig \ - ; then - # successful - update the validated params - check_config $paramsdir - exit 0 - fi -done +echo -e "\nEnrolled GPG card will now digitally sign /boot config files for future tamper evidence." +echo -e "As a result, Heads will prompt you to resign those files if any modification is detected at each reboot.\n" +echo -e "Please note that system updates will modify boot configurations. The kernel, initrd, Xen and grub files are normally modified." +echo -e "As a consequence, it is recommended that you reboot and sign /boot configuration changes after upgrading system components." +echo -e "Heads will prompt you on reboot to resign those files to attest that you approve those changes.\n" +if [ -z "$oem_gpg_User_PIN" ]; then + for tries in 1 2 3; do + echo -e "\nPlease enter your GPG card's User PIN to unlock card and sign /boot config files." + if sha256sum $param_files | gpg \ + --digest-algo SHA256 \ + --detach-sign \ + -a \ + > $paramsdir/kexec.sig \ + ; then + # successful - update the validated params + check_config $paramsdir + exit 0 + fi + done +else + echo -n "$oem_gpg_User_PIN" > /tmp/oem_gpg_User_PIN + if sha256sum $param_files | gpg --pinentry-mode loopback --batch --passphrase-file /tmp/oem_gpg_User_PIN \ + --detach-sign \ + --digest-algo SHA256 \ + -a \ + > $paramsdir/kexec.sig \ + ; then + # successful - update the validated params + shred -n 10 -z -u /tmp/oem_gpg_User_PIN 2> /dev/null + check_config $paramsdir + exit 0 + fi +fi +shred -n 10 -z -u /tmp/oem_gpg_User_PIN 2> /dev/null die "$paramsdir: Unable to sign kexec hashes" diff --git a/initrd/bin/kexec-unseal-key b/initrd/bin/kexec-unseal-key index e016f5bdc..84d95ad34 100755 --- a/initrd/bin/kexec-unseal-key +++ b/initrd/bin/kexec-unseal-key @@ -1,5 +1,5 @@ #!/bin/sh -# This will unseal and unecncrypt the drive encryption key from the TPM +# This will unseal and unencrypt the drive encryption key from the TPM # The TOTP secret will be shown to the user on each encryption attempt. # It will then need to be bundled into initrd that is booted with Qubes. set -e -o pipefail @@ -24,11 +24,11 @@ tpm nv_readvalue \ || die "Unable to read key from TPM NVRAM" for tries in 1 2 3; do - read -s -p "Enter unlock password (blank to abort): " tpm_password + read -s -p "Enter LUKS Disk Unlock Key passphrase (blank to abort): " tpm_password echo if [ -z "$tpm_password" ]; then - die "Aborting unseal disk encryption key" + die "Aborting unsealing LUKS Disk Unlock Key since no Disk Unlock Key passphrase was provided." fi if tpm unsealfile \ @@ -43,7 +43,7 @@ for tries in 1 2 3; do fi pcrs - warn "Unable to unseal disk encryption key" + warn "Unable to unseal Disk Unlock Key from TPM." done die "Retry count exceeded..." diff --git a/initrd/bin/key-init b/initrd/bin/key-init index bb4c1b5c9..42f811995 100755 --- a/initrd/bin/key-init +++ b/initrd/bin/key-init @@ -6,12 +6,16 @@ set -e -o pipefail # Import user's keys gpg --import /.gnupg/keys/*.key /.gnupg/keys/*.asc 2>/dev/null || true +#echo -e "\n\nUser's GPG keys in keyring:" +#gpg --list-keys +#echo "Press Enter key to continue..." +#read # Import trusted distro keys allowed for ISO signing gpg --homedir=/etc/distro/ --import /etc/distro/keys/* 2>/dev/null || true +# Add user's keys to the list of trusted keys for ISO signing +gpg --export | gpg --homedir=/etc/distro/ --import 2>/dev/null || true + #Set distro keys trust level to ultimate (trust anything that was signed with these keys) gpg --homedir=/etc/distro/ --list-keys --fingerprint --with-colons|sed -E -n -e 's/^fpr:::::::::([0-9A-F]+):$/\1:6:/p' |gpg --homedir=/etc/distro/ --import-ownertrust 2>/dev/null || true gpg --homedir=/etc/distro/ --update-trust 2>/dev/null || true - -# Add user's keys to the list of trusted keys for ISO signing -gpg --export | gpg --homedir=/etc/distro/ --import 2>/dev/null || true diff --git a/initrd/bin/mount-usb b/initrd/bin/mount-usb index 94946675a..0886a31f0 100755 --- a/initrd/bin/mount-usb +++ b/initrd/bin/mount-usb @@ -4,6 +4,17 @@ enable_usb +#OEM reownership, when attempting to load /media/oem-provisioning, +#requires usb-storage.ko module loaded, loaded here, modifying +#PCR 5, through /sbin/insmod script. +# +#We bypass that measurement here, so the PCR 5 is the same +#when calling kexec-seal-key in OEM mode then when calling +#kexec-unseal-key in normal boot mode. +if [ -e /boot/oem ]; then + alias insmod='busybox insmod' +fi + if ! lsmod | grep -q usb_storage; then insmod /lib/modules/usb-storage.ko \ || die "usb_storage: module load failed" diff --git a/initrd/bin/reencrypt-luks b/initrd/bin/reencrypt-luks new file mode 100755 index 000000000..e74af8ea2 --- /dev/null +++ b/initrd/bin/reencrypt-luks @@ -0,0 +1,93 @@ +#!/bin/sh +# Reencrypt LUKS container and change Disk Recovery Key associated passphrase (Slot 0: main slot) + +. /etc/functions +. /tmp/config + +select_luks_container() +{ + if [ -s /boot/kexec_key_devices.txt ]; then + LUKS=$(cut -d ' ' -f1 /boot/kexec_key_devices.txt) + else + #generate a list of devices to choose from that contain a LUKS header + blkid | cut -d ':' -f 1 | while read device;do cryptsetup isLuks $device;if [ $(echo $?) == 0 ]; then echo $device;fi; done | sort > /tmp/luks_devices.txt + file_selector "/tmp/luks_devices.txt" "Select LUKS container device" + if [ "$FILE" == "" ]; then + return + else + LUKS=$FILE + mount_boot + mount -o remount,rw /boot + echo "$LUKS $(cryptsetup luksUUID $LUKS)" > /boot/kexec_key_devices.txt + mount -o remount,ro /boot + fi + fi +} + +if [ $reownership_state = "luks_reencryption" ]; then + #if no USB oem-privisioning file provides actual Disk Recovery Key + if [ -z "$oem_luks_actual_Disk_Recovery_Key" ]; then + whiptail --title 'Reencrypt actual LUKS container with a new user selected strong passphrase?' \ + --msgbox "This will replace the actual Disk Recovery Key.\n\nThe passphrase associated with this key will be asked to the user in the\n following conditions:\n1-Every boot if no Disk unlock key was added to the TPM\n2-If the TPM fails (Hardware failure)\n3-If the firmware has been tampered with/upgraded/modified by the user\n\nThis process requires you to type the actual Disk Recovery Key passphrase\nand will delete the actual Disk unlock key released by the TPM into\nLUKS (slot 1) if present.\n\nAt the next prompt, you may be asked to select which file corresponds to\nthe LUKS device container. Normally, it should be /dev/sda2.\n\nHit Enter to continue." 30 90 + select_luks_container + whiptail --title 'Reencrypting LUKS container!' --msgbox \ + "Please enter current Disk Recovery Key passphrase (slot 0) to reencrypt\n LUKS container with a brand new encryption key\n\nHit Enter to continue." 30 60 + cryptsetup-reencrypt -B 32 --use-directio "$LUKS" --key-slot 0 + else + #USB "oem-privisioning" file provides actual Disk Recovery Key + echo -n "$oem_luks_actual_Disk_Recovery_Key" > /tmp/oem_luks_actual_Disk_Recovery_Key + select_luks_container + cryptsetup-reencrypt -B 32 --use-directio "$LUKS" --key-slot 0 --key-file /tmp/oem_luks_actual_Disk_Recovery_Key -h sha256 + fi + if [ $(echo $?) -ne 0 ]; then + whiptail --title 'Invalid LUKS Disk Recovery Key passphrase?' --msgbox \ + "The LUKS Disk Recovery Key password 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.\n\nTo do so, place ISO file and its signature file on root of USB drive,\n and select Boot from USB\n\nHit Enter to continue." 30 60 + shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null + continue + else + #Successfully reencrypted LUKS container with current Disk Recovery Key passphrase. Write successful state in oem file + if [ -e /boot/oem ];then + mount -o remount,rw /boot + echo "luks_reencrypted" >> /boot/oem + reownership_state="luks_password_change" + mount -o remount,ro /boot + shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null + fi + fi + continue +fi + +if [ $reownership_state == "luks_password_change" ]; then + #if actual or new Disk Recovery Key is not provisioned by USB oem-provisioning file + if [ -z "$oem_luks_actual_Disk_Recovery_Key" ] || [ -z "$oem_luks_new_Disk_Recovery_Key" ] ; then + 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 + + select_luks_container + + cryptsetup luksChangeKey "$LUKS" --key-slot 0 --tries 3 + else + #if actual and new Disk Recovery Key is provisioned by USB oem-provisioning file + select_luks_container + echo -n "$oem_luks_new_Disk_Recovery_Key" > /tmp/oem_luks_new_Disk_Recovery_Key + echo -n "$oem_luks_actual_Disk_Recovery_Key" > /tmp/oem_luks_actual_Disk_Recovery_Key + cryptsetup luksChangeKey "$LUKS" --key-slot 0 --key-file=/tmp/oem_luks_actual_Disk_Recovery_Key /tmp/oem_luks_new_Disk_Recovery_Key + fi + if [ $(echo $?) -ne 0 ]; then + 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 + shred -n 10 -z -u /tmp/oem_luks_new_Disk_Recovery_Key 2> /dev/null + shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null + continue + else + #Successfully changed LUKS Disk Recovery Key passphrase. Write successful state in oem file + if [ -e /boot/oem ];then + mount -o remount,rw /boot + echo "luks_passwd_changed" >> /boot/oem + mount -o remount,ro /boot + shred -n 10 -z -u /tmp/oem_luks_new_Disk_Recovery_Key 2> /dev/null + shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null + fi + fi + continue +fi diff --git a/initrd/bin/seal-libremkey b/initrd/bin/seal-libremkey index 7203b7198..7e5170ada 100755 --- a/initrd/bin/seal-libremkey +++ b/initrd/bin/seal-libremkey @@ -1,5 +1,5 @@ #!/bin/sh -# Retrieve the sealed TOTP secret and initialize a Librem Key with it +# Retrieve the sealed TOTP secret and initialize a LibremKey/NitroKey with it . /etc/functions @@ -29,7 +29,7 @@ tpm unsealfile \ || die "Unable to unseal HOTP secret" shred -n 10 -z -u "$HOTP_SEALED" 2> /dev/null -secret="`cat $HOTP_SECRET`" +secret="$(cat $HOTP_SECRET)" shred -n 10 -z -u "$HOTP_SECRET" 2> /dev/null # Store counter in file instead of TPM for now, as it conflicts with Heads @@ -52,19 +52,24 @@ counter_value=1 enable_usb if ! libremkey_hotp_verification info ; then - echo "Insert your Librem Key and press Enter to configure it" + echo "Insert your LibremKey/NitroKey and press Enter to configure it" read libremkey_hotp_verification info \ - || die "Unable to find Librem Key" + || die "Unable to find LibremKey/NitroKey" fi -read -s -p "Enter your Librem Key Admin PIN" admin_pin -echo +if [ -z "$oem_gpg_Admin_PIN" ]; then + read -s -p "Enter your LibremKey/NitroKey Admin PIN:" admin_pin + echo +else + admin_pin=$(echo -n "$oem_gpg_Admin_PIN") +fi -libremkey_hotp_initialize $admin_pin $secret $counter_value +libremkey_hotp_initialize "$admin_pin" "$secret" $counter_value if [ $? -ne 0 ]; then - read -s -p "Error setting HOTP secret, re-enter Admin PIN and try again:" admin_pin - libremkey_hotp_initialize $admin_pin $secret $counter_value \ + read -r -s -p "Error setting HOTP secret, re-enter Admin PIN and try again:" admin_pin + echo + libremkey_hotp_initialize "$admin_pin" "$secret" $counter_value \ || die "Setting HOTP secret failed" fi @@ -78,15 +83,15 @@ secret="" mount -o remount,rw /boot -counter_value=`expr $counter_value + 1` -echo $counter_value > $HOTP_COUNTER \ -|| die "Unable to create hotp counter file" +counter_value=$(expr $counter_value + 1) +echo "$counter_value" > $HOTP_COUNTER \ +|| die "Unable to create HOTP counter file" #sha256sum /tmp/counter-$counter > $HOTP_COUNTER \ -#|| die "Unable to create hotp counter file" +#|| die "Unable to create HOTP counter file" mount -o remount,ro /boot -echo "Librem Key initialized successfully. Press Enter to continue." +echo "LibremKey/NitroKey initialized successfully. Press Enter to continue." read exit 0 diff --git a/initrd/bin/seal-totp b/initrd/bin/seal-totp index f33449e58..d1f4df5e9 100755 --- a/initrd/bin/seal-totp +++ b/initrd/bin/seal-totp @@ -50,7 +50,7 @@ fi shred -n 10 -z -u "$TOTP_SECRET" 2> /dev/null -# 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. # # The permissions are 0 since there is nothing special diff --git a/initrd/bin/tpm-reset b/initrd/bin/tpm-reset index 8a8b9d1cc..6c0661ec8 100755 --- a/initrd/bin/tpm-reset +++ b/initrd/bin/tpm-reset @@ -5,20 +5,31 @@ echo '*****' echo '***** WARNING: This will erase all keys and secrets from the TPM' echo '*****' -read -s -p "New TPM owner password: " key_password -echo - -if [ -z "$key_password" ]; then - die "Empty owner password is not allowed" +if [ -z "$oem_TPM_Owner_Password" ]; then + key_password="1" + key_password2="2" +else + key_password="$oem_TPM_Owner_Password" + key_password2="$oem_TPM_Owner_Password" fi -read -s -p "Repeat owner password: " key_password2 -echo +while [ "$key_password" != "$key_password2" ]; do +{ + read -r -s -p "New TPM owner password: " key_password + echo + if [ -z "$key_password" ]; then + die "Empty TPM Owner password is not allowed" + fi + + read -r -s -p "Repeat TPM owner password: " key_password2 + echo + + if [ "$key_password" != "$key_password2" ]; then + die "TPM Owner passwords did not match" + fi +};done -if [ "$key_password" != "$key_password2" ]; then - die "Key passwords do not match" -fi # Make sure the TPM is ready to be reset tpm physicalpresence -s @@ -26,7 +37,7 @@ tpm physicalenable tpm physicalsetdeactivated -c tpm forceclear tpm physicalenable -tpm takeown -pwdo "$key_password" +tpm takeown -pwdo "$key_password" >/dev/null 2>&1 # And now turn it all back on tpm physicalpresence -s diff --git a/initrd/bin/unseal-totp b/initrd/bin/unseal-totp index c9c339b13..bb9fe20e5 100755 --- a/initrd/bin/unseal-totp +++ b/initrd/bin/unseal-totp @@ -16,7 +16,7 @@ tpm unsealfile \ -hk 40000000 \ -if "$TOTP_SEALED" \ -of "$TOTP_SECRET" \ -|| die "Unable to unseal totp secret" +|| die "Unable to unseal TOTP secret" shred -n 10 -z -u "$TOTP_SEALED" 2> /dev/null diff --git a/initrd/etc/functions b/initrd/etc/functions index 453590b84..6bd546b66 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -3,9 +3,20 @@ die() { echo >&2 "$*"; + read -p 'Hit enter to continue.' exit 1; } +debug(){ + echo >&2 "$*"; + read -p 'Hit enter to continue.' +} + +error() { + echo >&2 "$*"; + exit 1; +} + warn() { echo >&2 "$*"; } @@ -41,7 +52,7 @@ pause_recovery() { } pcrs() { - head -8 /sys/class/tpm/tpm0/pcrs + head -9 /sys/class/tpm/tpm0/pcrs } confirm_totp() @@ -118,6 +129,61 @@ enable_usb() fi } +file_selector() { + FILE="" + FILE_LIST=$1 + MENU_MSG=${2:-"Choose the file"} + # create file menu options + 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" + whiptail --clear --title "Select your File" \ + --menu "${MENU_MSG} [1-$n, a to abort]:" 20 120 8 \ + -- $MENU_OPTIONS \ + 2>/tmp/whiptail || die "Aborting" + + option_index=$(cat /tmp/whiptail) + + if [ "$option_index" = "a" ]; then + option="a" + return + fi + + option=$(head -n "$option_index" "$FILE_LIST" | tail -1) + if [ "$option" == "a" ]; then + return + fi + done + if [ -n "$option" ]; then + FILE=$option + fi + else + whiptail $CONFIG_ERROR_BG_COLOR --title 'ERROR: No Files Found' \ + --msgbox "No Files found matching the pattern. Aborting." 16 60 + exit 1 + fi +} + +mount_boot() +{ + # Mount local disk if it is not already mounted + if ! grep -q /boot /proc/mounts ; then + mount -o ro /boot \ + || recovery "Unable to mount /boot from $CONFIG_BOOT_DEV" + fi +} + confirm_gpg_card() { read \ @@ -140,7 +206,6 @@ confirm_gpg_card() || die "gpg card read failed" } - check_tpm_counter() { LABEL=${2:-3135106223} @@ -148,10 +213,15 @@ check_tpm_counter() # from it. if [ -r "$1" ]; then TPM_COUNTER=`grep counter- "$1" | cut -d- -f2` - else - warn "$1 does not exist; creating new TPM counter" - read -s -p "TPM Owner password: " tpm_password - echo + else + warn "$1 does not exist; creating new TPM counter" + if [ -z "$oem_TPM_Owner_Password" ]; then + read -s -p "TPM Owner password: " tpm_password + echo + else + tpm_password=$(echo -n "$oem_TPM_Owner_Password") + fi + tpm counter_create \ -pwdo "$tpm_password" \ -pwdc '' \ @@ -198,7 +268,8 @@ check_config() { if [ "$2" != "force" ]; then if ! sha256sum `find $1/kexec*.txt` | gpgv $1/kexec.sig - ; then - die 'Invalid signature on kexec boot params' + die 'Invalid signature on kexec boot params. Investigate/Update checksums and sign all files in /boot.' + #TODO: Show which files failed integrity check! fi fi diff --git a/initrd/init b/initrd/init index fd79d6773..b06079182 100755 --- a/initrd/init +++ b/initrd/init @@ -16,7 +16,7 @@ mkdir /proc /sys /dev /tmp /boot /media 2>&- 1>&- mount /dev 2>/dev/ttyprintk mount /proc 2>/dev/ttyprintk mount /sys 2>/dev/ttyprintk -mount /sys/firmware/efi/efivars +mount /sys/firmware/efi/efivars 2>/dev/ttyprintk # Setup the pty psudeo filesystem mkdir /dev/pts @@ -31,7 +31,6 @@ mkdir -p /tmp/secret # Now it is safe to print a banner if [ -r /etc/motd ]; then - cat /etc/motd cat /etc/motd > /dev/tty0 fi @@ -42,6 +41,15 @@ hwclock -l -s . /etc/functions . /etc/config +# Add our boot devices into the /etc/fstab, if they are defined +# in the configuration file. +if [ ! -z "$CONFIG_BOOT_DEV" ]; then + echo >> /etc/fstab "$CONFIG_BOOT_DEV /boot auto defaults,ro 0 0" +fi +if [ ! -z "$CONFIG_USB_BOOT_DEV" ]; then + echo >> /etc/fstab "$CONFIG_USB_BOOT_DEV /media auto defaults,ro 0 0" +fi + if [ "$CONFIG_COREBOOT" = "y" ]; then /bin/cbfs-init fi diff --git a/modules/gpg2 b/modules/gpg2 index 318a4cd11..566c1bec2 100644 --- a/modules/gpg2 +++ b/modules/gpg2 @@ -30,19 +30,12 @@ gpg2_configure := ./configure \ --disable-regex \ --disable-doc \ --disable-bzip2 \ - --disable-asm \ --disable-exec \ --disable-photo-viewers \ - --disable-keyserver-helpers \ --disable-ldap \ - --disable-hkp \ - --disable-finger \ - --disable-dns-srv \ - --disable-dns-cert \ --disable-regex \ --disable-nls \ --disable-all-tests \ - --disable-wks-server \ --disable-wks-tools \ --disable-gnutls \ --disable-dirmngr \ diff --git a/modules/libassuan b/modules/libassuan index 3c4e319aa..1b1d9fb6a 100644 --- a/modules/libassuan +++ b/modules/libassuan @@ -10,9 +10,7 @@ libassuan_configure := ./configure \ --host x86_64-linux-musl \ --prefix "/" \ --disable-static \ - --disable-nls \ --with-libgpg-error-prefix="$(INSTALL)" \ - --disable-asm \ libassuan_target := $(MAKE_JOBS) \ DESTDIR="$(INSTALL)" \ diff --git a/modules/libgcrypt b/modules/libgcrypt index aa7e1ef8e..d3c9dab4a 100644 --- a/modules/libgcrypt +++ b/modules/libgcrypt @@ -12,7 +12,6 @@ libgcrypt_configure := ./configure \ --disable-static \ --with-libgpg-error-prefix="$(INSTALL)" \ --disable-asm \ - --disable-nls \ libgcrypt_target := $(MAKE_JOBS) \ DESTDIR="$(INSTALL)" \ diff --git a/modules/libgpg-error b/modules/libgpg-error index 752e11aad..486eb2566 100644 --- a/modules/libgpg-error +++ b/modules/libgpg-error @@ -14,7 +14,6 @@ libgpg-error_configure := ./configure \ --disable-languages \ --disable-doc \ --disable-tests \ - --disable-asm \ libgpg-error_target := $(MAKE_JOBS) \ DESTDIR="$(INSTALL)" \ diff --git a/modules/libusb b/modules/libusb index b7fe959c4..9e63c8608 100644 --- a/modules/libusb +++ b/modules/libusb @@ -13,7 +13,6 @@ libusb_configure := ./configure\ --host i386-elf-linux\ --prefix "/"\ --disable-udev\ - --disable-tests\ # Run one build to generate the executables with the pre-defined # exec_prefix and datarootdir, then a second make to install the binaries diff --git a/modules/lvm2 b/modules/lvm2 index 91f0f53f0..bf18b818b 100644 --- a/modules/lvm2 +++ b/modules/lvm2 @@ -30,6 +30,8 @@ lvm2_configure := \ --disable-blkid_wiping \ --disable-cmirrord \ --disable-cache_check_needs_check \ + --with-thin=internal \ + --with-snapshots=internal \ --disable-thin_check_needs_check \ --with-cluster=none \ diff --git a/modules/npth b/modules/npth index e0f30c69e..a0cb09fca 100644 --- a/modules/npth +++ b/modules/npth @@ -10,9 +10,6 @@ npth_configure := ./configure \ --host x86_64-linux-musl \ --prefix "/" \ --disable-static \ - --disable-nls \ - --with-libgpg-error-prefix="$(INSTALL)" \ - --disable-asm \ npth_target := $(MAKE_JOBS) \ DESTDIR="$(INSTALL)" \ diff --git a/modules/pixman b/modules/pixman index 65a2e2008..8bd54a900 100644 --- a/modules/pixman +++ b/modules/pixman @@ -3,7 +3,7 @@ modules-$(CONFIG_CAIRO) += pixman pixman_version := 0.34.0 pixman_dir := pixman-$(pixman_version) pixman_tar := pixman-$(pixman_version).tar.gz -pixman_url := https://www.cairographics.org/releases/$(pixman_tar) +pixman_url := https://ftp.osuosl.org/pub/blfs/conglomeration/pixman/$(pixman_tar) pixman_hash := 21b6b249b51c6800dc9553b65106e1e37d0e25df942c90531d4c3997aa20a88e pixman_configure := \ diff --git a/oem-reownership/generate_diceware-eom-provisioning.sh b/oem-reownership/generate_diceware-eom-provisioning.sh new file mode 100755 index 000000000..abf7ce592 --- /dev/null +++ b/oem-reownership/generate_diceware-eom-provisioning.sh @@ -0,0 +1,66 @@ +#!/bin/bash +# 0- To use this script, install diceware first +# sudo dnf install diceware -y +# sudo apt-get install diceware -y +# +# Then +# 1- Run this script with ./generate_diceware-eom-provisioning.sh +# 2- Edit ./oem-provisioning.generated so all variiables are provisioned +# 3- Mount USB drive to /media ( eg. sudo mount /dev/sdb1 /media ) +# 4- Copy the file on USB drive ( eg. sudo cp /oem-provisioning.generated /media/oem-provisioning ) +# 5- Unmount USB drive to flush changes ( eg. sudo umount /media ) +# 6- Boot your newly received hardware with USB drive connected. +# 7- Enjoy! +# + +echo "#PLEASE KEEP THIS FILE IN A SAFE PLACE FOR FURTHER REFERENCE. " > ./oem-provisioning.generated +echo "#" >> ./oem-provisioning.generated +echo "#############" >> ./oem-provisioning.generated +echo "# IMPORTANT #" >> ./oem-provisioning.generated +echo "#############" >> ./oem-provisioning.generated +echo "# TO REMEMBER: Disk Recovery Key Passphrase (Used at system upgrades to recreate a Disk Unlock Key while setting a new boot default)" >> ./oem-provisioning.generated +echo "# !!!! IF YOU LOOSE THIS PASSPHRASE YOU'LL BE LOCKED OUT OF YOUR ENCRYPTED DISK !!!" >> ./oem-provisioning.generated +echo "# TO REMEMBER: Disk Unlock Key passphrase (Used at every boot, in between system upgrades)" >> ./oem-provisioning.generated +echo "# TO REMEMBER: GPG User PIN (Used to sign /boot config changes following system upgrades)" >> ./oem-provisioning.generated +echo "# After 3 bad attempts, you will need to unlock User PIN from Admin PIN" >> ./oem-provisioning.generated +echo "# TO REMEMBER: GPG Admin PIN (Used to manage the GPG card and to attest firmware changes you made.)" >> ./oem-provisioning.generated +echo "# After 3 bad attempts, YOU WILL BE LOCKED OUT OF THE CARD!" >> ./oem-provisioning.generated +echo "#" >> ./oem-provisioning.generated +echo "#" >> ./oem-provisioning.generated +echo "###########" >> ./oem-provisioning.generated +echo "# GPG #" >> ./oem-provisioning.generated +echo "###########" >> ./oem-provisioning.generated +echo "#The following GPG Key Admin PIN will be required from you to manage your LibremKey/Nitrokey" >> ./oem-provisioning.generated +echo "#It will be prompted from you under Heads through HOTP code generation to confirm firmware changes were yours" >> ./oem-provisioning.generated +while [[ ${#oem_gpg_Admin_PIN} -lt 8 || ${#oem_gpg_Admin_PIN} -gt 20 ]];do + oem_gpg_Admin_PIN=$(diceware -n 2) +done +echo "oem_gpg_Admin_PIN=$oem_gpg_Admin_PIN" >> ./oem-provisioning.generated +while [[ ${#oem_gpg_User_PIN} -lt 6 || ${#oem_gpg_User_PIN} -gt 20 ]];do + oem_gpg_User_PIN=$(diceware -n 2) +done +echo "#The following GPG Key User PIN will be required from you to Sign/Encrypt/Authenticate with your LibremKey/Nitrokey" >> ./oem-provisioning.generated +echo "#It will be prompted from you under Heads to confirm you are aware of /boot related changes" >> ./oem-provisioning.generated +echo "oem_gpg_User_PIN=$oem_gpg_User_PIN" >> ./oem-provisioning.generated +echo "#The following will be used to identify you publicly in generated public key from Heads." >> ./oem-provisioning.generated +echo "#If you intend to upload the generated public key online, you are invited provision the following accordingly" >> ./oem-provisioning.generated +echo "oem_gpg_real_name=" >> ./oem-provisioning.generated +echo "oem_gpg_email=" >> ./oem-provisioning.generated +echo "#The following is used to differenciate different public keys attached to the same name and e-mail address" >> ./oem-provisioning.generated +echo "oem_gpg_comment=" >> ./oem-provisioning.generated +echo "#" >> ./oem-provisioning.generated +echo "########################################" >> ./oem-provisioning.generated +echo "# LUKS Disk Encryption Key Passphrases #" >> ./oem-provisioning.generated +echo "########################################" >> ./oem-provisioning.generated +echo "#The actual Disk Recovery Key passphrase needs to match the passphrase provided by the OEM to unlock actual Disk encrypted drive" >> ./oem-provisioning.generated +echo "oem_luks_actual_Disk_Recovery_Key=" >> ./oem-provisioning.generated +echo "#The new Disk Recovery Key passphrase will replace the Disk Recovery Key password after reencrypting the container with the actual one" >> ./oem-provisioning.generated +echo "oem_luks_new_Disk_Recovery_Key=$(diceware -n 5)" >> ./oem-provisioning.generated +echo "#The Disk Unlock Key passphrase will be used to lauch default boot option at each system startup, and is bound to measured boot integrity attested by the TPM." >> ./oem-provisioning.generated +echo "oem_luks_Disk_Unlock_Key=$(diceware -n 3)" >> ./oem-provisioning.generated +echo "#" >> ./oem-provisioning.generated +echo "#################################" >> ./oem-provisioning.generated +echo "# Trusted Platform Module (TPM) #" >> ./oem-provisioning.generated +echo "#################################" >> ./oem-provisioning.generated +echo "#The TPM Owner passphrase is needed just to own the machine. It is suggested to use the same passphrase as in Admin PIN to limit the number of secrets to remember." >> ./oem-provisioning.generated +echo "oem_TPM_Owner_Password=$oem_gpg_Admin_PIN" >> ./oem-provisioning.generated diff --git a/oem-reownership/oem-provisioning.example b/oem-reownership/oem-provisioning.example new file mode 100644 index 000000000..b0e5017fa --- /dev/null +++ b/oem-reownership/oem-provisioning.example @@ -0,0 +1,198 @@ +########### +# OEM # +########### +# To activate OEM reownership wizard, under Heads recovery console, do: +# mount /boot +# mount -o remount,rw /boot +# echo "oem_name=COMPANY NAME" > /boot/oem +# mount -o remount,ro /boot +# reboot +# +# To activate OEM automatic provisioning, the content of this file needs to be found by Heads under: +# /media/oem-provisioning +# By default, the USB drive is mounted from /dev/sdb1 but "mount-usb" will find the usb drive and mount it under /media +# +# Replace variables content with your own! +# +#The following needs to be put in /boot/oem for OEM name to be shown at OEM Reownership wizard first screen. Else it is going to be "your OEM". +#oem_name=Insurgo Open Technologies +# +#On a recovery shell, type the UP arrow key until you reach top of the history buffer. A command is proposed for you to change "YOUR COMPANY" +# to your own. The hardware is then ready to ship and the wizard will accompany the user in reowning the hardware and OEM secrets on next reboot. +# +# You should invite the user into using "generate_diceware-eom-provisioning.sh" script in the current directory, +# which uses diceware to prefeed "oem-provisioning.generated" with proper secrets. +# The user would then need to put that file under "oem-provisioning" on the root of a dedicated USB drive and connect on first boot of +# received hardware to reduce user errors and friction of having to enter those secrets manually. + +######### +# GPG # +######### +# GPG card function in Heads: +# The LibremKey/NitroKey is a traditional GPG card added with HMAC-based One-time Password (HOTP) which permits +# to seal integrity measurements into the GPG card memory. +# +# As a functional result, at each boot, the card will flash its LED green if the measured boot integrity +# is atttested or red in case of a mismatch. This provable security measure is called tamper-evidence and +# informs the user that the Firmware (BIOS chips content) has been tampered with, or modified, and doesn't +# match expected measurements expected by the Trusted Platform Module (TPM) and validated by the GPG card. +# +# Heads traditionally stores Trusted Module Platform (TPM) Time-based One-time Password (TOTP) code in a +# smartphone through the scanning of a QR code into an OTP authenticator application when the TPM is reowned or +# when a firmware update is applied. Through the reownership process, the firmware will be modified by inserting +# public PGP key into the firmware, which will invalidate measurements and require the TOTP/HOTP to be resealed. +# The TPM itself will be reowned by the user, requesting him to set a passphrase. +# +# *** You should use both TOTP/HOTP so you can still validate attested integiryt in case your GPG card gets lost *** +# +# HOTP/TOTP are functionally similar, while the LibremKey/Nitrokey permits to validate integrity visually in an +# instant without having to unlock the smartphone, open the OTP application and verify that a 6 digits code there +# is the same that is shown on the screen. +# HOTP LibremKey/Nitrokey feature is complementory to the TOTP and shares the same codebase. +# +# Heads also depends on the GPG card to store used private key outside of prying eyes, securely stored on the +# Smartcard. When factory resetting the card, only the public key is inserted into the rom, which is used +# to automatically validate the integiryt of /boot files through checksuming and validating the the result +# matches what is signed with the private key on the GPG card. +# +# Heads will warn the user each time boot configuration changes. +# That will happen when the Operating System applies core system updates (Xen, Kernel, initrd (drivers) +# and grub configuration) while notifying the user of any addition/supression of files expected to be found +# in the /boot partition. +# +# GPG usage in Heads: +# Heads will prompt the user for: +# User PIN: +# Sign boot configuration changes. +# Admin PIN: +# Seal Firmware changes through HOTP +# +# IMPORTANT: +# The user should always reboot the system and sign configuration changes as soon as possible after system upgrades +# to attest the responsibility and ownership of the changes. +# +# The user should always be cautious about TOTP/HOTP errors if he didn't update the firmware himself. +# +# Heads primary goal is to attest of the integrity of the firmware and /boot files. +# That integrity attestation is based on those two practices that REQUIRES TO BE FOLLOWED. +# +# PIN Notes: GPG PINs are protected in the SmartCard. After 3 bad attempts, the SmartCard locks that account. +# When the User PIN is locked, the Admin PIN can be used to unlock User PIN. +# When the Admin PIN is locked, a Reset Code can be used to unlock Admin PIN. +# This is not provisioned by default. You will have to set one manually yourself. +# +# You can define an additional "Reset Code" to reset the Admin PIN manually by doing: +# gpg --card-edit +# admin +# passwd +# 4 - set the Reset Code +# Type Admin PIN +# +#GPG SmartCard desired Admin PIN to provision GPG factory reset. +# Admin PIN manages Admin functions of the card through gpg --edit-card admin functions, +# In Heads, the Admin PIN is required to seal HOTP secret into NitroKey/LibremKey when firmware has been modified. +# +# NOTES: If the GPG card is lost, the user won't be able to seal firmware changes through HOTP. +# Size constaints: minimum 8 characters, maximum 20 characters, WITHOUT SPACES! +# (Else HOTP cannot be sealed. It's a seal-libremkey limitation) +# No need to go crazy here. Remember that 3 bad attempts locks the account. One or two Diceware words are enough. +# Use KeepassXC password manager or something like https://www.rempe.us/diceware/#eff +oem_gpg_Admin_PIN=InsurgoTech +# +#GPG SmartCard desired User PIN to provision GPG factory reset. +# User PIN manages user functions of the card. It is used to encrypt files and e-mails, sign files and e-mails +# and authenticate the user in daily operations when used in combination with the public key generated. +# That public key needs to be kept, as it is impossible to export it from the smartcard. +# In Heads, the User PIN is required to sign boot configuration changes. +# At each boot, the imported public key counterpart is used to validate the checksums of the files signed with the card. +# +# NOTES: If the GPG card is lost, the user won't be able to sign system changes. +# Size constaints: minimum 6 characters, maximum 20 characters +# No need to go crazy here. Remember that 3 bad attempts locks the account. One or two Diceware words are enough. +# Use KeepassXC password manager or something like https://www.rempe.us/diceware/#eff +oem_gpg_User_PIN=Insurgo +#GPG SmartCard desired Real Name to provision GPG factory reset. +# This will be used to construct the ID of the public key: "Real Name (Comment) email@address.org" +# +# Size constaints: minimum 5 characters. +oem_gpg_real_name=Insurgo Integrity Delivered Attestation Attestation LibremKey +#GPG SmartCard desired E-mail address to provision GPG factory reset. +# This will be used to construct the ID of the public key: "Real Name (Comment) email@address.org" +# Note that some services requires that e-mail address to be real and will send an e-mail to validate it. +# If you intend to use the GPG card to encrypt/sign e-mails, this is a good idea to provide main e-mail account here. +oem_gpg_email=insurgo@riseup.net +#GPG SmartCard desired Comment to provision GPG factory reset. +# This will be used to construct the ID of the public key: "Real Name (Comment) email@address.org" +# If you have multiple cards associated with the same E-mail address, this is a good place to name it's usage difference +oem_gpg_comment=FACTORY RESET ME + +########## +# LUKS # +########## +# LUKS containers are used in Linux to encrypt whole filesystems. +# The whole idea behind OEM reownership depends on the LUKS reencryption of the container from the user when hardware +# is received. Otherwise, the OEM would know the cloned image LUKS Disk Recovery Key and could hand it to authorities. +# This provisioning wizard starts by asking you to enter the actual LUKS Disk Recovery Key passphrase to reencrypt the +# container completely, before changing it's passphrase with user selected one. +# +# This LUKS Disk Recovery Key, if provided by the OEM **** SHOULD NOT BE MODIFIED ***** +oem_luks_actual_Disk_Recovery_Key=InsurgoTech +# This is where you want to define your new Disk Recovery Key passphrase, which will be associated to the reencrypted LUKS +# container after the OEM wizard is over and become the Disk Recovery Key passphrase. +# +# This provisioning wizard continues by asking you to enter the desired LUKS Disk Recovery Key passphrase and changes +# it. +# +# The Disk Recovery Key will be prompted to the user in the following cases: +# 1-Every boot if no Disk Unlock Key was added to the TPM (NOT RECOMMENDED! could be captured and used on cloned disk) +# 2-If the TPM fails (Hardware failure) +# 3-If the firmware has been tampered with/upgraded/modified by the user +# +# NOTES: If the Disk Recovery Key Passphrase is lost, the user won't be able to set a new Disk Unlock Key. +# More importantly, in the case of a Operating System core update (Xen, Kernel, initrd (drivers) or grub config, +# the Default Boot option will be invalidated, and the only way to boot the system will be by typing this +# Disk Recovery Key Passphrase. ********** CHOOSE IT CAREFULLY SO YOU CAN EASILY REMEMBER IT *********** +# +# Size constaints: select a Diceware passphrase of at least 3 words. 6 is better. +# No need to go crazy here. It's better to have a shorter but strong passphrase you remember and not type often +# then a strong passphrase that locks you out of the system and requires you to reinstall. +# Use KeepassXC password manager or something alike https://www.rempe.us/diceware/#eff +oem_luks_new_Disk_Recovery_Key=InsurgoTech +# Disk Unlock Key Passphrase is the passphrase the user will be required to type under Heads to start the system. +# +# The Disk Unlock Key is another security feature enforced by Heads that makes your computer more trustworthy. +# The Disk Unlock Key is released by the Trusted Platform Module (TPM), a cryptographic component on which +# depends Heads to measure and attest firmware integrity, and released only if the measurements of the firmware +# are intact (sealed). In the case the firmware has been modified, that the user lost/forgot his GPG card, +# the Disk Unlock key passphrase will refuse to release the actual Disk Unlock Key and will not boot, unless +# you to type the Disk Recovery Key passphrase. +# +# Heads would not be able to unseal neither TOTP/HOTP in case measurements mismatche and will warn the user. +# +# The Disk Unlock Key passphrase will also not be able to unlock the disk if the LUKS header is not +# consistent with what was sealed into the TPM when selecting a default boot option. +# +# Functionnaly, selecting a default boot option and setting a Disk Unlock Key is a good security measure against +# prying eyes, let them be camera recording or over the shoulder passphrase capture. +# Since that Key is bounded with firmware integrity measurements from the TPM, that passphrase is bound to this +# computer only. +# +# A third party which would clone the disk and attempt to access its content later would succeed only if +# Disk Recovery Key passphrase was typed, not the Disk Unlock Key passphrase. +# +# Size constaints: Best is to select a Diceware passphrase of at least 4 words. 6+ is better. +# Use KeypassXC password manager or something like https://www.rempe.us/diceware/#eff +# No need to go crazy here. An attacker would have 3 attempts at a time when booting Heads. +# Use KeepassXC password manager or something like https://www.rempe.us/diceware/#eff +# You will be prompted to change this passphrase at every core Operating System upgrades since the default boot +# option will be modified. +oem_luks_Disk_Unlock_Key=Insurgo + +################################### +# Trusted Platform Module (TPM) # +################################### +# The TPM passphrase is required when sealing the Disk Unlock Key when selecting a new default boot option, +# combined with the GPG User PIN. +# +# It is recommended to reuse GPG Admin Passphrase/Password here, to not unecessarily multiply secrets to remember. +oem_TPM_Owner_Password=InsurgoTech From 79b33901fdeeea77b507243c99a7a26013372230 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Tue, 23 Apr 2019 18:35:53 -0400 Subject: [PATCH 03/91] LibremKey -> Librem Key --- initrd/bin/gpg-gui.sh | 2 +- initrd/bin/gui-init | 14 +++++++------- initrd/bin/kexec-seal-key | 4 ++-- initrd/bin/seal-libremkey | 10 +++++----- .../generate_diceware-eom-provisioning.sh | 4 ++-- oem-reownership/oem-provisioning.example | 10 +++++----- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/initrd/bin/gpg-gui.sh b/initrd/bin/gpg-gui.sh index 646ffa8c9..6e271283f 100755 --- a/initrd/bin/gpg-gui.sh +++ b/initrd/bin/gpg-gui.sh @@ -76,7 +76,7 @@ while true; do 'a' ' Add GPG key to standalone BIOS image + flash' \ 'l' ' List GPG keys in your keyring' \ 'g' ' Generate GPG keys on a USB security token' \ - 'F' ' Factory Reset Nitrokey Pro v2/LibremKey GPG Card' \ + 'F' ' Factory Reset Nitrokey Pro v2/Librem Key GPG Card' \ 'x' ' Exit' \ 2>/tmp/whiptail || recovery "GUI menu failed" diff --git a/initrd/bin/gui-init b/initrd/bin/gui-init index 46863a084..1d1382ecb 100755 --- a/initrd/bin/gui-init +++ b/initrd/bin/gui-init @@ -131,11 +131,11 @@ update_totp() echo "Scan the QR code to add the new TOTP secret" /bin/seal-totp $CONFIG_BOARD if [ -x /bin/libremkey_hotp_verification ]; then - echo "Once you have scanned the QR code, hit Enter to configure your LibremKey/Nitrokey" + echo "Once you have scanned the QR code, hit Enter to configure your Librem Key/Nitrokey" read /bin/seal-libremkey while [ $? -ne 0 ];do - echo -e "\n\nSealing HOTP secret into LibremKey/Nitrokey failed. Let's try again by resealing both TOTP and HOTP." + echo -e "\n\nSealing HOTP secret into Librem Key/Nitrokey failed. Let's try again by resealing both TOTP and HOTP." update_totp /bin/seal-libremkey done @@ -224,7 +224,7 @@ check_onboarding_progress() if [ $? -ne 0 ];then #Show Onboarding menu once. whiptail --title 'Hardware reownership Wizard' --msgbox \ - "The received hardware is currently owned by $oem_name.\nWe will change that.\n\nThis Wizard will otherwise make you own your own hardware by:\n1-Reencrypting encrypted drive content (LUKS container)\n2-Changing LUKS Disk Recovery Key and it's passphrase\n3-Resetting your LibremKey/Nitrokey Pro v2 to factory defaults\n4-Setting User and Admin PINs into your LibremKey/NitroKey\n4-Generating keys in it, exporting public key and\n importing it in the rom prior to reprogramming the SPI flash with it\n6-Taking integrity measures of all /boot files and sign the resulting\n checksum file with yourLibremKey/Nitrokey Pro\n6-Owning your Trusted Platform Module (TPM)\n\nScan the QR Code with an OTP app only after Reset the TPM last phase.\n\nHit Enter to continue." 20 20 + "The received hardware is currently owned by $oem_name.\nWe will change that.\n\nThis Wizard will otherwise make you own your own hardware by:\n1-Reencrypting encrypted drive content (LUKS container)\n2-Changing LUKS Disk Recovery Key and it's passphrase\n3-Resetting your Librem Key/Nitrokey Pro v2 to factory defaults\n4-Setting User and Admin PINs into your Librem Key/NitroKey\n4-Generating keys in it, exporting public key and\n importing it in the rom prior to reprogramming the SPI flash with it\n6-Taking integrity measures of all /boot files and sign the resulting\n checksum file with yourLibrem Key/Nitrokey Pro\n6-Owning your Trusted Platform Module (TPM)\n\nScan the QR Code with an OTP app only after Reset the TPM last phase.\n\nHit Enter to continue." 20 20 whiptail --title 'Hardware reownership Wizard' --msgbox \ "On the next screen, MAKE SURE THAT THE HOTP CODE IS: 'Success'\n\nIf it's not, reboot your hardware with your Librem/Nitrokey inserted.\n\nIf the HOTP code is still invalid, your hardware may been tampered with in\ntransit. Contact $oem_name." 20 20 totp_confirm="O" @@ -301,7 +301,7 @@ reset_disk_unlock_key() HOTP=`unseal-hotp` enable_usb if ! libremkey_hotp_verification info ; then - whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'WARNING: Please Insert Your LibremKey/Nitrokey' --msgbox "Your LibremKey/Nitrokey was not detected.\n\nPlease insert your LibremKey/Nitrokey" 30 90 + whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'WARNING: Please Insert Your Librem Key/Nitrokey' --msgbox "Your Librem Key/Nitrokey was not detected.\n\nPlease insert your Librem Key/Nitrokey" 30 90 fi # Don't output HOTP codes to screen, so as to make replay attacks harder libremkey_hotp_verification check "$HOTP" @@ -314,7 +314,7 @@ reset_disk_unlock_key() MAIN_MENU_BG_COLOR=$CONFIG_ERROR_BG_COLOR ;; * ) - HOTP="Error checking code, Insert LibremKey/Nitrokey and retry" + HOTP="Error checking code, Insert Librem Key/Nitrokey and retry" MAIN_MENU_BG_COLOR=$CONFIG_WARNING_BG_COLOR ;; esac @@ -415,7 +415,7 @@ while true; do HOTP=`unseal-hotp` enable_usb if ! libremkey_hotp_verification info ; then - whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'WARNING: Please Insert Your LibremKey/Nitrokey' --msgbox "Your LibremKey/Nitrokey was not detected.\n\nPlease insert your LibremKey/Nitrokey" 30 90 + whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'WARNING: Please Insert Your Librem Key/Nitrokey' --msgbox "Your Librem Key/Nitrokey was not detected.\n\nPlease insert your Librem Key/Nitrokey" 30 90 fi # Don't output HOTP codes to screen, so as to make replay attacks harder libremkey_hotp_verification check "$HOTP" @@ -428,7 +428,7 @@ while true; do MAIN_MENU_BG_COLOR=$CONFIG_ERROR_BG_COLOR ;; * ) - HOTP="Error checking code, Insert LibremKey/Nitrokey and retry" + HOTP="Error checking code, Insert Librem Key/Nitrokey and retry" MAIN_MENU_BG_COLOR=$CONFIG_WARNING_BG_COLOR ;; esac diff --git a/initrd/bin/kexec-seal-key b/initrd/bin/kexec-seal-key index 4243ec7ba..880f10b54 100755 --- a/initrd/bin/kexec-seal-key +++ b/initrd/bin/kexec-seal-key @@ -98,8 +98,8 @@ cat "$KEY_DEVICES" | cut -d\ -f1 | xargs /bin/qubes-measure-luks \ || die "Unable to measure the LUKS headers" luks_pcr=`tpm calcfuturepcr -ix 16 -if /tmp/luksDump.txt` -# LibremKey/Nitrokey loads USB modules which changes PCR5. -# In the event LibremKey/Nitrokey is enabled, skip verification of PCR5 +# Librem Key/Nitrokey loads USB modules which changes PCR5. +# In the event Librem Key/Nitrokey is enabled, skip verification of PCR5 if [ -x /bin/libremkey_hotp_verification ]; then pcr_5="X" else diff --git a/initrd/bin/seal-libremkey b/initrd/bin/seal-libremkey index 7e5170ada..381273109 100755 --- a/initrd/bin/seal-libremkey +++ b/initrd/bin/seal-libremkey @@ -1,5 +1,5 @@ #!/bin/sh -# Retrieve the sealed TOTP secret and initialize a LibremKey/NitroKey with it +# Retrieve the sealed TOTP secret and initialize a Librem Key/NitroKey with it . /etc/functions @@ -52,14 +52,14 @@ counter_value=1 enable_usb if ! libremkey_hotp_verification info ; then - echo "Insert your LibremKey/NitroKey and press Enter to configure it" + echo "Insert your Librem Key/NitroKey and press Enter to configure it" read libremkey_hotp_verification info \ - || die "Unable to find LibremKey/NitroKey" + || die "Unable to find Librem Key/NitroKey" fi if [ -z "$oem_gpg_Admin_PIN" ]; then - read -s -p "Enter your LibremKey/NitroKey Admin PIN:" admin_pin + read -s -p "Enter your Librem Key/NitroKey Admin PIN:" admin_pin echo else admin_pin=$(echo -n "$oem_gpg_Admin_PIN") @@ -91,7 +91,7 @@ echo "$counter_value" > $HOTP_COUNTER \ #|| die "Unable to create HOTP counter file" mount -o remount,ro /boot -echo "LibremKey/NitroKey initialized successfully. Press Enter to continue." +echo "Librem Key/NitroKey initialized successfully. Press Enter to continue." read exit 0 diff --git a/oem-reownership/generate_diceware-eom-provisioning.sh b/oem-reownership/generate_diceware-eom-provisioning.sh index abf7ce592..bbec5d9e2 100755 --- a/oem-reownership/generate_diceware-eom-provisioning.sh +++ b/oem-reownership/generate_diceware-eom-provisioning.sh @@ -30,7 +30,7 @@ echo "#" >> ./oem-provisioning.generated echo "###########" >> ./oem-provisioning.generated echo "# GPG #" >> ./oem-provisioning.generated echo "###########" >> ./oem-provisioning.generated -echo "#The following GPG Key Admin PIN will be required from you to manage your LibremKey/Nitrokey" >> ./oem-provisioning.generated +echo "#The following GPG Key Admin PIN will be required from you to manage your Librem Key/Nitrokey" >> ./oem-provisioning.generated echo "#It will be prompted from you under Heads through HOTP code generation to confirm firmware changes were yours" >> ./oem-provisioning.generated while [[ ${#oem_gpg_Admin_PIN} -lt 8 || ${#oem_gpg_Admin_PIN} -gt 20 ]];do oem_gpg_Admin_PIN=$(diceware -n 2) @@ -39,7 +39,7 @@ echo "oem_gpg_Admin_PIN=$oem_gpg_Admin_PIN" >> ./oem-provisioning.generated while [[ ${#oem_gpg_User_PIN} -lt 6 || ${#oem_gpg_User_PIN} -gt 20 ]];do oem_gpg_User_PIN=$(diceware -n 2) done -echo "#The following GPG Key User PIN will be required from you to Sign/Encrypt/Authenticate with your LibremKey/Nitrokey" >> ./oem-provisioning.generated +echo "#The following GPG Key User PIN will be required from you to Sign/Encrypt/Authenticate with your Librem Key/Nitrokey" >> ./oem-provisioning.generated echo "#It will be prompted from you under Heads to confirm you are aware of /boot related changes" >> ./oem-provisioning.generated echo "oem_gpg_User_PIN=$oem_gpg_User_PIN" >> ./oem-provisioning.generated echo "#The following will be used to identify you publicly in generated public key from Heads." >> ./oem-provisioning.generated diff --git a/oem-reownership/oem-provisioning.example b/oem-reownership/oem-provisioning.example index b0e5017fa..ab68b7e7e 100644 --- a/oem-reownership/oem-provisioning.example +++ b/oem-reownership/oem-provisioning.example @@ -29,7 +29,7 @@ # GPG # ######### # GPG card function in Heads: -# The LibremKey/NitroKey is a traditional GPG card added with HMAC-based One-time Password (HOTP) which permits +# The Librem Key/NitroKey is a traditional GPG card added with HMAC-based One-time Password (HOTP) which permits # to seal integrity measurements into the GPG card memory. # # As a functional result, at each boot, the card will flash its LED green if the measured boot integrity @@ -45,10 +45,10 @@ # # *** You should use both TOTP/HOTP so you can still validate attested integiryt in case your GPG card gets lost *** # -# HOTP/TOTP are functionally similar, while the LibremKey/Nitrokey permits to validate integrity visually in an +# HOTP/TOTP are functionally similar, while the Librem Key/Nitrokey permits to validate integrity visually in an # instant without having to unlock the smartphone, open the OTP application and verify that a 6 digits code there # is the same that is shown on the screen. -# HOTP LibremKey/Nitrokey feature is complementory to the TOTP and shares the same codebase. +# HOTP Librem Key/Nitrokey feature is complementory to the TOTP and shares the same codebase. # # Heads also depends on the GPG card to store used private key outside of prying eyes, securely stored on the # Smartcard. When factory resetting the card, only the public key is inserted into the rom, which is used @@ -90,7 +90,7 @@ # #GPG SmartCard desired Admin PIN to provision GPG factory reset. # Admin PIN manages Admin functions of the card through gpg --edit-card admin functions, -# In Heads, the Admin PIN is required to seal HOTP secret into NitroKey/LibremKey when firmware has been modified. +# In Heads, the Admin PIN is required to seal HOTP secret into NitroKey/Librem Key when firmware has been modified. # # NOTES: If the GPG card is lost, the user won't be able to seal firmware changes through HOTP. # Size constaints: minimum 8 characters, maximum 20 characters, WITHOUT SPACES! @@ -115,7 +115,7 @@ oem_gpg_User_PIN=Insurgo # This will be used to construct the ID of the public key: "Real Name (Comment) email@address.org" # # Size constaints: minimum 5 characters. -oem_gpg_real_name=Insurgo Integrity Delivered Attestation Attestation LibremKey +oem_gpg_real_name=Insurgo Integrity Delivered Attestation Attestation Librem Key #GPG SmartCard desired E-mail address to provision GPG factory reset. # This will be used to construct the ID of the public key: "Real Name (Comment) email@address.org" # Note that some services requires that e-mail address to be real and will send an e-mail to validate it. From d0efe53e5b164a206e4b5838f88132115aa25a26 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Wed, 24 Apr 2019 16:23:19 -0400 Subject: [PATCH 04/91] Corrections in numbering of OEM onboarding menu. --- initrd/bin/gui-init | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/initrd/bin/gui-init b/initrd/bin/gui-init index 1d1382ecb..e589eeea2 100755 --- a/initrd/bin/gui-init +++ b/initrd/bin/gui-init @@ -224,7 +224,7 @@ check_onboarding_progress() if [ $? -ne 0 ];then #Show Onboarding menu once. whiptail --title 'Hardware reownership Wizard' --msgbox \ - "The received hardware is currently owned by $oem_name.\nWe will change that.\n\nThis Wizard will otherwise make you own your own hardware by:\n1-Reencrypting encrypted drive content (LUKS container)\n2-Changing LUKS Disk Recovery Key and it's passphrase\n3-Resetting your Librem Key/Nitrokey Pro v2 to factory defaults\n4-Setting User and Admin PINs into your Librem Key/NitroKey\n4-Generating keys in it, exporting public key and\n importing it in the rom prior to reprogramming the SPI flash with it\n6-Taking integrity measures of all /boot files and sign the resulting\n checksum file with yourLibrem Key/Nitrokey Pro\n6-Owning your Trusted Platform Module (TPM)\n\nScan the QR Code with an OTP app only after Reset the TPM last phase.\n\nHit Enter to continue." 20 20 + "The received hardware is currently owned by $oem_name.\nWe will change that.\n\nThis Wizard will otherwise make you own your own hardware by:\n1-Reencrypting encrypted drive content (LUKS container)\n2-Changing LUKS Disk Recovery Key and it's passphrase\n3-Resetting your Librem Key/Nitrokey Pro v2 to factory defaults\n4-Setting User and Admin PINs into your Librem Key/NitroKey\n5-Generating keys in it, exporting public key and\n importing it in the ROM prior to reprogramming the SPI flash with it\n6-Taking integrity measures of all /boot files and sign the resulting\n checksum file with your Librem Key/Nitrokey Pro\n7-Reowning your Trusted Platform Module (TPM)\n\nScan the QR Code with an OTP app only after Reset the TPM last phase.\n\nHit Enter to continue." 20 20 whiptail --title 'Hardware reownership Wizard' --msgbox \ "On the next screen, MAKE SURE THAT THE HOTP CODE IS: 'Success'\n\nIf it's not, reboot your hardware with your Librem/Nitrokey inserted.\n\nIf the HOTP code is still invalid, your hardware may been tampered with in\ntransit. Contact $oem_name." 20 20 totp_confirm="O" From 5361ad1e98f8993c987c1a39dae496187e106f03 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Wed, 24 Apr 2019 18:05:11 -0400 Subject: [PATCH 05/91] Small fixes following PR comments -remove die calls in whiptail reported cases which are handled anyway -move oem functions into etc/functions to have a cleaner gui-init --- initrd/bin/flash-gui.sh | 2 +- initrd/bin/gpg-gui.sh | 4 +- initrd/bin/gui-init | 236 ---------------------------------------- initrd/etc/functions | 193 ++++++++++++++++++++++++++++++++ 4 files changed, 196 insertions(+), 239 deletions(-) diff --git a/initrd/bin/flash-gui.sh b/initrd/bin/flash-gui.sh index 22621e644..b013007b4 100755 --- a/initrd/bin/flash-gui.sh +++ b/initrd/bin/flash-gui.sh @@ -104,7 +104,7 @@ while true; do /bin/flash.sh "$ROM" fi whiptail --title 'ROM Flashed Successfully' \ - --msgbox "$ROM flashed successfully. Press Enter to reboot" 16 60 + --msgbox "$ROM flashed successfully.\nPress Enter to reboot" 16 60 umount /media /bin/reboot else diff --git a/initrd/bin/gpg-gui.sh b/initrd/bin/gpg-gui.sh index 97fa29dc7..2f527b86a 100755 --- a/initrd/bin/gpg-gui.sh +++ b/initrd/bin/gpg-gui.sh @@ -89,7 +89,7 @@ while true; do "a" ) if (whiptail --title 'ROM and GPG public key required' \ --yesno "This requires you insert a USB drive containing:\n* Your GPG public key (*.key or *.asc)\n* Your BIOS image (*.rom)\n\nAfter you select these files, this program will reflash your BIOS\n\nDo you want to proceed?" 16 90) then - mount_usb || die "Unable to mount USB device" + mount_usb if grep -q /media /proc/mounts ; then find /media -name '*.key' > /tmp/filelist.txt find /media -name '*.asc' >> /tmp/filelist.txt @@ -161,7 +161,7 @@ while true; do "r" ) if (whiptail --title 'GPG public key required' \ --yesno "This requires you insert a USB drive containing:\n* Your GPG public key (*.key or *.asc)\n\nNormally, the file should be named public.key\n\nAfter you select this file, this program will copy and reflash your BIOS\n\nDo you want to proceed?" 16 90) then - mount_usb || die "Unable to mount USB device" + mount_usb if grep -q /media /proc/mounts ; then find /media -name '*.key' > /tmp/filelist.txt find /media -name '*.asc' >> /tmp/filelist.txt diff --git a/initrd/bin/gui-init b/initrd/bin/gui-init index e589eeea2..82ccc568d 100755 --- a/initrd/bin/gui-init +++ b/initrd/bin/gui-init @@ -6,51 +6,7 @@ CONFIG_BOOT_GUI_MENU_NAME='Heads Boot Menu' . /etc/functions . /tmp/config -file_selector() { - FILE="" - FILE_LIST=$1 - MENU_MSG=${2:-"Choose the file"} - # create file menu options - 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" - whiptail --clear --title "Select your File" \ - --menu "${MENU_MSG} [1-$n, a to abort]:" 20 120 8 \ - -- $MENU_OPTIONS \ - 2>/tmp/whiptail || die "Aborting" - - option_index=$(cat /tmp/whiptail) - - if [ "$option_index" = "a" ]; then - option="a" - return - fi - option=$(head -n "$option_index" "$FILE_LIST" | tail -1) - if [ "$option" == "a" ]; then - return - fi - done - if [ -n "$option" ]; then - FILE=$option - fi - else - whiptail $CONFIG_ERROR_BG_COLOR --title 'ERROR: No Files Found' \ - --msgbox "No Files found matching the pattern. Aborting." 16 60 - exit 1 - fi -} verify_global_hashes() { # Check the hashes of all the files, ignoring signatures for now @@ -145,198 +101,6 @@ update_totp() fi /bin/reboot } -read_oem_file() -{ - echo "Mounting USB drive to provision OEM reownership from /media/oem-provisioning..." - /bin/mount-usb || warn "Unable to mount USB device. Continuing" - if [ -e /media/oem-provisioning ]; then - oem_gpg_Admin_PIN=$(grep "oem_gpg_Admin_PIN" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_gpg_Admin_PIN" ]; then - export oem_gpg_Admin_PIN="$oem_gpg_Admin_PIN" - else - unset oem_gpg_Admin_PIN - fi - - oem_gpg_User_PIN=$(grep "oem_gpg_User_PIN" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_gpg_User_PIN" ]; then - export oem_gpg_User_PIN="$oem_gpg_User_PIN" - else - unset oem_gpg_User_PIN - fi - - oem_gpg_real_name=$(grep "oem_gpg_real_name" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_gpg_real_name" ]; then - export oem_gpg_real_name="$oem_gpg_real_name" - else - unset oem_gpg_real_name - fi - - oem_gpg_email=$(grep "oem_gpg_email" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_gpg_email" ]; then - export oem_gpg_email="$oem_gpg_email" - else - unset oem_gpg_email - fi - - oem_gpg_comment=$(grep "oem_gpg_comment" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_gpg_comment" ]; then - export oem_gpg_comment="$oem_gpg_comment" - else - unset oem_gpg_comment - fi - - oem_luks_actual_Disk_Recovery_Key=$(grep "oem_luks_actual_Disk_Recovery_Key" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_luks_actual_Disk_Recovery_Key" ]; then - export oem_luks_actual_Disk_Recovery_Key="$oem_luks_actual_Disk_Recovery_Key" - else - unset oem_luks_actual_Disk_Recovery_Key - fi - - oem_luks_new_Disk_Recovery_Key=$(grep "oem_luks_new_Disk_Recovery_Key" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_luks_new_Disk_Recovery_Key" ]; then - export oem_luks_new_Disk_Recovery_Key="$oem_luks_new_Disk_Recovery_Key" - else - unset oem_luks_new_Disk_Recovery_Key - fi - - oem_luks_Disk_Unlock_Key=$(grep "oem_luks_Disk_Unlock_Key" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_luks_Disk_Unlock_Key" ]; then - export oem_luks_Disk_Unlock_Key="$oem_luks_Disk_Unlock_Key" - else - unset oem_luks_Disk_Unlock_Key - fi - - oem_TPM_Owner_Password=$(grep "oem_TPM_Owner_Password" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_TPM_Owner_Password" ]; then - export oem_TPM_Owner_Password="$oem_TPM_Owner_Password" - else - unset oem_TPM_Owner_Password - fi - - export oem_configuration_read=1 - fi -} -check_onboarding_progress() -{ - mount_boot - if [ -e /boot/oem ]; then - res=$(grep onboarding /boot/oem 2>&1 > /dev/null) - if [ $? -ne 0 ];then - #Show Onboarding menu once. - whiptail --title 'Hardware reownership Wizard' --msgbox \ - "The received hardware is currently owned by $oem_name.\nWe will change that.\n\nThis Wizard will otherwise make you own your own hardware by:\n1-Reencrypting encrypted drive content (LUKS container)\n2-Changing LUKS Disk Recovery Key and it's passphrase\n3-Resetting your Librem Key/Nitrokey Pro v2 to factory defaults\n4-Setting User and Admin PINs into your Librem Key/NitroKey\n5-Generating keys in it, exporting public key and\n importing it in the ROM prior to reprogramming the SPI flash with it\n6-Taking integrity measures of all /boot files and sign the resulting\n checksum file with your Librem Key/Nitrokey Pro\n7-Reowning your Trusted Platform Module (TPM)\n\nScan the QR Code with an OTP app only after Reset the TPM last phase.\n\nHit Enter to continue." 20 20 - whiptail --title 'Hardware reownership Wizard' --msgbox \ - "On the next screen, MAKE SURE THAT THE HOTP CODE IS: 'Success'\n\nIf it's not, reboot your hardware with your Librem/Nitrokey inserted.\n\nIf the HOTP code is still invalid, your hardware may been tampered with in\ntransit. Contact $oem_name." 20 20 - totp_confirm="O" - echo $totp_confirm > /tmp/whiptail - mount -o remount,rw /boot - echo "onboarding" >> /boot/oem - mount -o remount,ro /boot - fi - res=$(grep luks_reencrypted /boot/oem 2>&1 > /dev/null) - if [ $? -ne 0 ];then - export reownership_state="luks_reencryption" - totp_confirm="R" - echo $totp_confirm > /tmp/whiptail - return - fi - res=$(grep luks_passwd_changed /boot/oem 2>&1 > /dev/null) - if [ $? -ne 0 ];then - export reownership_state="luks_password_change" - totp_confirm="R" - return - fi - res=$(grep gpg_factory_resetted /boot/oem 2>&1 > /dev/null) - if [ $? -ne 0 ];then - /bin/factory-reset-nitrokey-libremkey.sh - return - fi - res=$(grep tpm_reowned /boot/oem 2>&1 > /dev/null) - if [ $? -ne 0 ];then - totp_confirm="p" - echo $totp_confirm > /tmp/whiptail - return - fi - if [ $(grep -E "luks_reencrypted|luks_passwd_changed|gpg_factory_resetted|tpm_reowned" /boot/oem | uniq | wc -l) -eq 4 ];then - if [ $HOTP = "Success" ];then - mount -o remount,rw /boot - rm /boot/oem - mount -o remount,ro /boot - unset totp_confirm - unset reownership_state - whiptail --title 'DISK UNLOCK KEY ADVICE 1/3' --msgbox \ - "***You SHOULD SET a new Disk Unlock Key for your own data privacy!!!***\n\nDoing so, a witness will only be able to type observed Disk Unlock\n Key passphrase from this computer and won't be able on a cloned\n copy of this disk.\n\nThe release of Disk Unlock Key happens ONLY if TPM attests firmware\nintegrity, and only if Disk Unlock Key passphrase is valid.\n\nPlease hit Enter to continue" 30 60 - - whiptail --title 'DISK UNLOCK KEY ADVICE 2/3' --msgbox \ - "Otherwise, typing your Disk Recovery Key passphrase at boot puts you\nat risk. Someone could clone your disk and type that witnessed\npassphrase and access your data both locally and from a cloned\ndisk.\n\nCoupled with a strong passphrase, this improves your data privacy.\nCONSIDER YOURSELF WARNED.\n\nPlease hit Enter to continue" 30 60 - - whiptail --title 'DISK UNLOCK KEY ADVICE 3/3' --msgbox \ - "To set Disk Unlock Key, released by the TPM only if firmware integrity\n is attested:\n\nSelect from Main menu:\n\nAdvanced Options menu -> Other Boot Options -> Show OS boot menu\n1-Then select the first boot option proposed (dynamic option)\n2-Then,answer Y when asked to add Disk Unlock Key to the TPM.\n\nYou will be prompted to set one in the following steps.\n\nPlease hit Enter to continue" 30 60 - return - else - #Deal with corner case where after inserting key in previous step, HOTP seal fails with provided good password. - #In that case, we regenerate HOTP and TOTP - totp_confirm="g" - echo $totp_confirm > /tmp/whiptail - fi - fi - else - reset_disk_unlock_key - return - fi -} -reset_disk_unlock_key() -{ - mount_boot - - if [ "$CONFIG_TPM" = n ]; then - TOTP="NO TPM" - else - TOTP=`unseal-totp` - if [ $? -ne 0 ]; then - echo "Error generating TOTP code. We will regenerate it now." - update_totp - continue - elif [ -x /bin/libremkey_hotp_verification ]; then - HOTP=`unseal-hotp` - enable_usb - if ! libremkey_hotp_verification info ; then - whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'WARNING: Please Insert Your Librem Key/Nitrokey' --msgbox "Your Librem Key/Nitrokey was not detected.\n\nPlease insert your Librem Key/Nitrokey" 30 90 - fi - # Don't output HOTP codes to screen, so as to make replay attacks harder - libremkey_hotp_verification check "$HOTP" - case "$?" in - 0 ) - HOTP="Success" - ;; - 4 ) - HOTP="Invalid code" - MAIN_MENU_BG_COLOR=$CONFIG_ERROR_BG_COLOR - ;; - * ) - HOTP="Error checking code, Insert Librem Key/Nitrokey and retry" - MAIN_MENU_BG_COLOR=$CONFIG_WARNING_BG_COLOR - ;; - esac - else - HOTP='N/A' - fi - - if [ $HOTP = "Success" ];then - mount -o remount,rw /boot - rm /boot/reset_disk_unlock_key - mount -o remount,ro /boot - verify_global_hashes - kexec-select-boot -m -b /boot -c "grub.cfg" -g - continue - else - echo -e "HOTP status: $HOTP\n\nHit Enter to regenerate new TOTP/HOTP codes." - read - update_totp - fi - continue - fi -} mount_boot if [ -e /boot/oem ];then diff --git a/initrd/etc/functions b/initrd/etc/functions index 6bd546b66..6caac2d71 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -311,3 +311,196 @@ replace_config() { combine_configs() { cat /etc/config* > /tmp/config } +read_oem_file() +{ + echo "Mounting USB drive to provision OEM reownership from /media/oem-provisioning..." + /bin/mount-usb || warn "Unable to mount USB device. Continuing" + if [ -e /media/oem-provisioning ]; then + oem_gpg_Admin_PIN=$(grep "oem_gpg_Admin_PIN" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_gpg_Admin_PIN" ]; then + export oem_gpg_Admin_PIN="$oem_gpg_Admin_PIN" + else + unset oem_gpg_Admin_PIN + fi + + oem_gpg_User_PIN=$(grep "oem_gpg_User_PIN" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_gpg_User_PIN" ]; then + export oem_gpg_User_PIN="$oem_gpg_User_PIN" + else + unset oem_gpg_User_PIN + fi + + oem_gpg_real_name=$(grep "oem_gpg_real_name" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_gpg_real_name" ]; then + export oem_gpg_real_name="$oem_gpg_real_name" + else + unset oem_gpg_real_name + fi + + oem_gpg_email=$(grep "oem_gpg_email" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_gpg_email" ]; then + export oem_gpg_email="$oem_gpg_email" + else + unset oem_gpg_email + fi + + oem_gpg_comment=$(grep "oem_gpg_comment" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_gpg_comment" ]; then + export oem_gpg_comment="$oem_gpg_comment" + else + unset oem_gpg_comment + fi + + oem_luks_actual_Disk_Recovery_Key=$(grep "oem_luks_actual_Disk_Recovery_Key" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_luks_actual_Disk_Recovery_Key" ]; then + export oem_luks_actual_Disk_Recovery_Key="$oem_luks_actual_Disk_Recovery_Key" + else + unset oem_luks_actual_Disk_Recovery_Key + fi + + oem_luks_new_Disk_Recovery_Key=$(grep "oem_luks_new_Disk_Recovery_Key" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_luks_new_Disk_Recovery_Key" ]; then + export oem_luks_new_Disk_Recovery_Key="$oem_luks_new_Disk_Recovery_Key" + else + unset oem_luks_new_Disk_Recovery_Key + fi + + oem_luks_Disk_Unlock_Key=$(grep "oem_luks_Disk_Unlock_Key" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_luks_Disk_Unlock_Key" ]; then + export oem_luks_Disk_Unlock_Key="$oem_luks_Disk_Unlock_Key" + else + unset oem_luks_Disk_Unlock_Key + fi + + oem_TPM_Owner_Password=$(grep "oem_TPM_Owner_Password" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_TPM_Owner_Password" ]; then + export oem_TPM_Owner_Password="$oem_TPM_Owner_Password" + else + unset oem_TPM_Owner_Password + fi + + export oem_configuration_read=1 + umount /media + fi +} +check_onboarding_progress() +{ + mount_boot + if [ -e /boot/oem ]; then + res=$(grep onboarding /boot/oem 2>&1 > /dev/null) + if [ $? -ne 0 ];then + #Show Onboarding menu once. + whiptail --title 'Hardware reownership Wizard' --msgbox \ + "The received hardware is currently owned by $oem_name.\nWe will change that.\n\nThis Wizard will otherwise make you own your own hardware by:\n1-Reencrypting encrypted drive content (LUKS container)\n2-Changing LUKS Disk Recovery Key and it's passphrase\n3-Resetting your Librem Key/Nitrokey Pro v2 to factory defaults\n4-Setting User and Admin PINs into your Librem Key/NitroKey\n5-Generating keys in it, exporting public key and\n importing it in the ROM prior to reprogramming the SPI flash with it\n6-Taking integrity measures of all /boot files and sign the resulting\n checksum file with your Librem Key/Nitrokey Pro\n7-Reowning your Trusted Platform Module (TPM)\n\nScan the QR Code with an OTP app only after Reset the TPM last phase.\n\nHit Enter to continue." 20 20 + whiptail --title 'Hardware reownership Wizard' --msgbox \ + "On the next screen, MAKE SURE THAT THE HOTP CODE IS: 'Success'\n\nIf it's not, reboot your hardware with your Librem/Nitrokey inserted.\n\nIf the HOTP code is still invalid, your hardware may been tampered with in\ntransit. Contact $oem_name." 20 20 + totp_confirm="O" + echo $totp_confirm > /tmp/whiptail + mount -o remount,rw /boot + echo "onboarding" >> /boot/oem + mount -o remount,ro /boot + fi + res=$(grep luks_reencrypted /boot/oem 2>&1 > /dev/null) + if [ $? -ne 0 ];then + export reownership_state="luks_reencryption" + totp_confirm="R" + echo $totp_confirm > /tmp/whiptail + return + fi + res=$(grep luks_passwd_changed /boot/oem 2>&1 > /dev/null) + if [ $? -ne 0 ];then + export reownership_state="luks_password_change" + totp_confirm="R" + return + fi + res=$(grep gpg_factory_resetted /boot/oem 2>&1 > /dev/null) + if [ $? -ne 0 ];then + /bin/factory-reset-nitrokey-libremkey.sh + return + fi + res=$(grep tpm_reowned /boot/oem 2>&1 > /dev/null) + if [ $? -ne 0 ];then + totp_confirm="p" + echo $totp_confirm > /tmp/whiptail + return + fi + if [ $(grep -E "luks_reencrypted|luks_passwd_changed|gpg_factory_resetted|tpm_reowned" /boot/oem | uniq | wc -l) -eq 4 ];then + if [ $HOTP = "Success" ];then + mount -o remount,rw /boot + rm /boot/oem + mount -o remount,ro /boot + unset totp_confirm + unset reownership_state + whiptail --title 'DISK UNLOCK KEY ADVICE 1/3' --msgbox \ + "***You SHOULD SET a new Disk Unlock Key for your own data privacy!!!***\n\nDoing so, a witness will only be able to type observed Disk Unlock\n Key passphrase from this computer and won't be able on a cloned\n copy of this disk.\n\nThe release of Disk Unlock Key happens ONLY if TPM attests firmware\nintegrity, and only if Disk Unlock Key passphrase is valid.\n\nPlease hit Enter to continue" 30 60 + + whiptail --title 'DISK UNLOCK KEY ADVICE 2/3' --msgbox \ + "Otherwise, typing your Disk Recovery Key passphrase at boot puts you\nat risk. Someone could clone your disk and type that witnessed\npassphrase and access your data both locally and from a cloned\ndisk.\n\nCoupled with a strong passphrase, this improves your data privacy.\nCONSIDER YOURSELF WARNED.\n\nPlease hit Enter to continue" 30 60 + + whiptail --title 'DISK UNLOCK KEY ADVICE 3/3' --msgbox \ + "To set Disk Unlock Key, released by the TPM only if firmware integrity\n is attested:\n\nSelect from Main menu:\n\nAdvanced Options menu -> Other Boot Options -> Show OS boot menu\n1-Then select the first boot option proposed (dynamic option)\n2-Then,answer Y when asked to add Disk Unlock Key to the TPM.\n\nYou will be prompted to set one in the following steps.\n\nPlease hit Enter to continue" 30 60 + return + else + #Deal with corner case where after inserting key in previous step, HOTP seal fails with provided good password. + #In that case, we regenerate HOTP and TOTP + totp_confirm="g" + echo $totp_confirm > /tmp/whiptail + fi + fi + else + reset_disk_unlock_key + return + fi +} +reset_disk_unlock_key() +{ + mount_boot + + if [ "$CONFIG_TPM" = n ]; then + TOTP="NO TPM" + else + TOTP=`unseal-totp` + if [ $? -ne 0 ]; then + echo "Error generating TOTP code. We will regenerate it now." + update_totp + continue + elif [ -x /bin/libremkey_hotp_verification ]; then + HOTP=`unseal-hotp` + enable_usb + if ! libremkey_hotp_verification info ; then + whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'WARNING: Please Insert Your Librem Key/Nitrokey' --msgbox "Your Librem Key/Nitrokey was not detected.\n\nPlease insert your Librem Key/Nitrokey" 30 90 + fi + # Don't output HOTP codes to screen, so as to make replay attacks harder + libremkey_hotp_verification check "$HOTP" + case "$?" in + 0 ) + HOTP="Success" + ;; + 4 ) + HOTP="Invalid code" + MAIN_MENU_BG_COLOR=$CONFIG_ERROR_BG_COLOR + ;; + * ) + HOTP="Error checking code, Insert Librem Key/Nitrokey and retry" + MAIN_MENU_BG_COLOR=$CONFIG_WARNING_BG_COLOR + ;; + esac + else + HOTP='N/A' + fi + + if [ $HOTP = "Success" ];then + mount -o remount,rw /boot + rm /boot/reset_disk_unlock_key + mount -o remount,ro /boot + verify_global_hashes + kexec-select-boot -m -b /boot -c "grub.cfg" -g + continue + else + echo -e "HOTP status: $HOTP\n\nHit Enter to regenerate new TOTP/HOTP codes." + read + update_totp + fi + continue + fi +} From ecbc01e4943191525b7df867eb6a0f649a90a2eb Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Wed, 24 Apr 2019 20:04:15 -0400 Subject: [PATCH 06/91] kexec-save-default: - fix regression : putting back possibility to set a default boot option without having to seal it in TPM. - Verified all possibilities: without sealing in TPM, going back to set a new default sealed, and going back once again to reuse past used configured devices. --- initrd/bin/kexec-save-default | 135 ++++++++++++---------------------- 1 file changed, 47 insertions(+), 88 deletions(-) diff --git a/initrd/bin/kexec-save-default b/initrd/bin/kexec-save-default index c3283f611..4e9b186e4 100755 --- a/initrd/bin/kexec-save-default +++ b/initrd/bin/kexec-save-default @@ -50,6 +50,47 @@ else devices_suggest=$(echo $devices_suggest) fi +if [ "$num_lvm" -gt 1 ]; then + //untested + selected_lvmdev_not_existing=1 + while [ $selected_lvmdev_not_existing -ne 0 ];do + { + read \ + -p "Encrypted LVM group? choose between: $lvm_suggest: " \ + lvm_volume_group + + result=$(echo "$lvm_suggest" | grep -q "$lvm_volume_group") || selected_lvmdev_not_existing=1 + if [ $? == 0 ]; then + selected_lvmdev_not_existing=0 + fi + };done +elif [ "$num_lvm" -eq 1 ]; then + echo "Single Encrypted LVM group found at $lvm_suggest. Using it." + lvm_volume_group=$lvm_suggest +else + echo "No encrypted LVM Group found." +fi + +if [ "$num_devices" -gt 1 ]; then + selected_luksdev_not_existing=1 + while [ $selected_luksdev_not_existing -ne 0 ];do + { + read \ + -p "Encrypted devices? (choose between: $devices_suggest): " \ + key_devices + + result=$(echo "$devices_suggest" | grep -q "$key_devices") || selected_luksdev_not_existing=1 + if [ $? == 0 ]; then + selected_luksdev_not_existing=0 + fi + };done +elif [ "$num_devices" -eq 1 ]; then + echo "Single Encrypted Disk found at $devices_suggest. Using it." + key_devices=$devices_suggest +else + echo "No encrypted devices found." +fi + if [ ! -r "$TMP_MENU_FILE" ]; then die "No menu options available, please run kexec-select-boot" @@ -73,50 +114,9 @@ if [ "$CONFIG_TPM" = "y" ]; then echo if [ "$add_key_confirm" = "y" ] || [ "$add_key_confirm" = "Y" ] || [ -z "$add_key_confirm" ]; then - if [ "$num_lvm" -gt 1 ]; then - //untested - selected_lvmdev_not_existing=1 - while [ $selected_lvmdev_not_existing -ne 0 ];do - { - read \ - -p "Encrypted LVM group? choose between: $lvm_suggest: " \ - lvm_volume_group - - result=$(echo "$lvm_suggest" | grep -q "$lvm_volume_group") || selected_lvmdev_not_existing=1 - if [ $? == 0 ]; then - selected_lvmdev_not_existing=0 - fi - };done - elif [ "$num_lvm" -eq 1 ]; then - echo "Single Encrypted LVM group found at $lvm_suggest. Using it." - lvm_volume_group=$lvm_suggest - else - echo "No encrypted LVM Group found." - fi - - if [ "$num_devices" -gt 1 ]; then - selected_luksdev_not_existing=1 - while [ $selected_luksdev_not_existing -ne 0 ];do - { - read \ - -p "Encrypted devices? (choose between: $devices_suggest): " \ - key_devices - - result=$(echo "$devices_suggest" | grep -q "$key_devices") || selected_luksdev_not_existing=1 - if [ $? == 0 ]; then - selected_luksdev_not_existing=0 - fi - };done - elif [ "$num_devices" -eq 1 ]; then - echo "Single Encrypted Disk found at $devices_suggest. Using it." - key_devices=$devices_suggest - else - echo "No encrypted devices found." - fi - - save_key="y" + save_key="y" else - die "User chose to not add Disk Unlock Key to the TPM" + warn "User chose to not add Disk Unlock Key to the TPM. It can be done manually later on by selecting a new default boot option." fi else read \ @@ -161,47 +161,6 @@ if [ "$CONFIG_TPM" = "y" ]; then if [ -z "$lvm_volume_group" ] && [ -n "$old_lvm_volume_group" ]; then lvm_volume_group="$old_lvm_volume_group" fi - else - if [ "$num_lvm" -eq 1 ]; then - echo "Single Encrypted LVM group found at $lvm_suggest. Using it." - lvm_volume_group="$lvm_suggest" - elif [ "$num_lvm" -gt 1 ]; then - //untested - selected_lvmdev_not_existing=1 - while [ $selected_lvmdev_not_existing -ne 0 ];do - { - read \ - -p "Encrypted LVM group? (choose between: $lvm_suggest): " \ - lvm_volume_group - - result=$(echo "$lvm_suggest" | grep -q "$lvm_volume_group") || selected_lvmdev_not_existing=1 - if [ $? == 0 ]; then - selected_lvmdev_not_existing=0 - fi - };done - else - echo "No encrypted LVM Group found." - fi - - if [ "$num_devices" -eq 1 ]; then - echo "Single Encrypted Disk found at $devices_suggest. Using it." - key_devices="$devices_suggest" - elif [ "$num_devices" -gt 1 ]; then - selected_luksdev_not_existing=1 - while [ $selected_luksdev_not_existing -ne 0 ];do - { - read \ - -p "Encrypted devices? (choose between: $devices_suggest): " \ - key_devices - - result=$(echo "$devices_suggest" | grep -q "$key_devices") || selected_luksdev_not_existing=1 - if [ $? == 0 ]; then - selected_luksdev_not_existing=0 - fi - };done - else - echo "No encrypted devices found." - fi fi fi @@ -213,11 +172,11 @@ if [ "$CONFIG_TPM" = "y" ]; then else die "No LVM Group nor encrypted devices provided." fi + + echo -e "\nRunning kexec-save-key with params: $save_key_params\n" + kexec-save-key $save_key_params \ + || die "Failed to save the Disk Unlock Key" fi - - echo -e "\nRunning kexec-save-key with params: $save_key_params\n" - kexec-save-key $save_key_params \ - || die "Failed to save the Disk Unlock Key" fi # try to switch to rw mode From 3318f67343f28766bab1cc3963bff90b49bd0169 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Wed, 24 Apr 2019 20:06:50 -0400 Subject: [PATCH 07/91] functions: rm -> rm -f on /boot/reset_disk_unlock_key to suppress error on console when not existing --- initrd/etc/functions | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/initrd/etc/functions b/initrd/etc/functions index 6caac2d71..53f743e07 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -491,7 +491,7 @@ reset_disk_unlock_key() if [ $HOTP = "Success" ];then mount -o remount,rw /boot - rm /boot/reset_disk_unlock_key + rm -f /boot/reset_disk_unlock_key mount -o remount,ro /boot verify_global_hashes kexec-select-boot -m -b /boot -c "grub.cfg" -g From 20b0fbf37d59f82b55bd85a7de2553d27e342d2f Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Wed, 24 Apr 2019 20:30:39 -0400 Subject: [PATCH 08/91] oem-reownership/oem.example : explain the usage of /boot/oem and when and why /media/oem-provisioning values are used in each stage --- oem-reownership/oem.example | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100755 oem-reownership/oem.example diff --git a/oem-reownership/oem.example b/oem-reownership/oem.example new file mode 100755 index 000000000..65300be29 --- /dev/null +++ b/oem-reownership/oem.example @@ -0,0 +1,21 @@ +#OEM name shown on onboarding screen if found under /boot/oem when OEM Reownership Wizard starts +oem_name=Insurgo Open Technologies +# +#The following are states being checked against prior to entering that specific stage. +# Once a stage is done, it is appended under /boot/oem +# +#If not found in file, shows Onboarding first message containing oem_name above if defined, else "your OEM" is shown +onboarding +#When not present in this file, reencrypts LUKS container with oem_luks_actual_Disk_Recovery_Key defined under /media/oem-provisioning +luks_reencrypted +#When not present in this file, changes oem_luks_actual_Disk_Recovery_Key with oem_luks_new_Disk_Recovery_Key defined under /media/oem-provisioning +luks_passwd_changed +#When not present in this file, factory resets Librem Key/NitroKey with: oem_gpg_Admin_PIN, oem_gpg_User_PIN, oem_gpg_real_name, oem_gpg_email, oem_gpg_comment, defined under /media/oem-provisioning. +#The wizard generates new keypairs, injects the public key and trust database into the ROM and reboots. +#Upon reboot, the oem_gpg_Admin_PIN is used to automatically seal HOTP secret into the Librem Key/NitroKey +gpg_factory_resetted +#When not present in this file, reown the TPM with oem_TPM_Owner_Password, which is recommended to be the same as oem_gpg_Admin_PIN +tpm_reowned +#Once all stages are done, the Wizard removes /boot/oem, and ensures that /boot file checksum file is generated and signed with oem_gpg_User_PIN. +# +#Then the wizard finally launches the selection of a new boot default, and asks the user if he wants to modifie the disk and if he wants to define a Disk Unlock Key. In such case, oem_TPM_Owner_Password is used to seal a new TOTP secret, oem_gpg_Admin_PIN is used to seal a new HOTP secret, and oem_gpg_User_PIN is used to sign configuration files checksums that changed under /boot. From b49d9cd1c5e9d2a6c3ecd8e320c58e68830f861b Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Wed, 24 Apr 2019 20:37:41 -0400 Subject: [PATCH 09/91] Removing useless dies in gui scripts --- initrd/bin/flash-gui.sh | 2 +- initrd/bin/gui-init | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/initrd/bin/flash-gui.sh b/initrd/bin/flash-gui.sh index b013007b4..ce123b8e2 100755 --- a/initrd/bin/flash-gui.sh +++ b/initrd/bin/flash-gui.sh @@ -86,7 +86,7 @@ while true; do f|c ) if (whiptail --title 'Flash the BIOS with a new ROM' \ --yesno "This requires you insert a USB drive containing:\n* Your BIOS image (*.rom)\n\nAfter you select this file, this program will reflash your BIOS\n\nDo you want to proceed?" 16 90) then - mount_usb || die "Unable to mount USB device." + mount_usb if grep -q /media /proc/mounts ; then find /media -name '*.rom' > /tmp/filelist.txt file_selector "/tmp/filelist.txt" "Choose the ROM to flash" diff --git a/initrd/bin/gui-init b/initrd/bin/gui-init index 82ccc568d..08fb1a618 100755 --- a/initrd/bin/gui-init +++ b/initrd/bin/gui-init @@ -59,7 +59,7 @@ update_checksums() mount_boot mount -o rw,remount /boot - cd /boot || die "Not able to change directory to /boot." + cd /boot find ./ -type f ! -name '*kexec*' | xargs sha256sum > /boot/kexec_hashes.txt DEFAULT_FILES=$(cat /boot/kexec_default_hashes.txt | cut -f3 -d ' ') echo $DEFAULT_FILES | xargs sha256sum > /boot/kexec_default_hashes.txt From 330a54f3227b20b3ef58c7ef42c47525ccfdb6a9 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Fri, 26 Apr 2019 11:24:37 -0400 Subject: [PATCH 10/91] Code cleanup. Removal of file_selector function, since it now exists under etc/functions and sourced by those scripts --- initrd/bin/flash-gui.sh | 46 ----------------------------------------- initrd/bin/gpg-gui.sh | 45 ---------------------------------------- 2 files changed, 91 deletions(-) diff --git a/initrd/bin/flash-gui.sh b/initrd/bin/flash-gui.sh index ce123b8e2..bb6a82b59 100755 --- a/initrd/bin/flash-gui.sh +++ b/initrd/bin/flash-gui.sh @@ -22,52 +22,6 @@ mount_usb(){ fi } -file_selector() { - FILE="" - FILE_LIST=$1 - MENU_MSG=${2:-"Choose the file"} -# create file menu options - 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" - whiptail --clear --title "Select your File" \ - --menu "${MENU_MSG} [1-$n, a to abort]:" 20 120 8 \ - -- $MENU_OPTIONS \ - 2>/tmp/whiptail || die "Aborting" - - option_index=$(cat /tmp/whiptail) - - if [ "$option_index" = "a" ]; then - option="a" - return - fi - - option=`head -n $option_index $FILE_LIST | tail -1` - if [ "$option" == "a" ]; then - return - fi - done - if [ -n "$option" ]; then - FILE=$option - fi - else - whiptail $CONFIG_ERROR_BG_COLOR --title 'ERROR: No Files Found' \ - --msgbox "No Files found matching the pattern. Aborting." 16 60 - exit 1 - fi -} - while true; do unset menu_choice whiptail --clear --title "Firmware Management Menu" \ diff --git a/initrd/bin/gpg-gui.sh b/initrd/bin/gpg-gui.sh index 2f527b86a..1ca045a33 100755 --- a/initrd/bin/gpg-gui.sh +++ b/initrd/bin/gpg-gui.sh @@ -22,51 +22,6 @@ mount_usb(){ fi } -file_selector() { - FILE="" - FILE_LIST=$1 - MENU_MSG=${2:-"Choose the file"} -# create file menu options - 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" - whiptail --clear --title "Select your File" \ - --menu "${MENU_MSG} [1-$n, a to abort]:" 20 120 8 \ - -- $MENU_OPTIONS \ - 2>/tmp/whiptail || die "Aborting" - - option_index=$(cat /tmp/whiptail) - - if [ "$option_index" = "a" ]; then - option="a" - return - fi - - option=`head -n $option_index $FILE_LIST | tail -1` - if [ "$option" == "a" ]; then - return - fi - done - if [ -n "$option" ]; then - FILE=$option - fi - else - whiptail $CONFIG_ERROR_BG_COLOR --title 'ERROR: No Files Found' \ - --msgbox "No Files found matching the pattern. Aborting." 16 60 - exit 1 - fi -} while true; do unset menu_choice From 99148c8768c91c8edfed4e539e965c1223b1fc71 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Fri, 26 Apr 2019 11:37:00 -0400 Subject: [PATCH 11/91] Typo correction --- oem-reownership/oem.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oem-reownership/oem.example b/oem-reownership/oem.example index 65300be29..ff1ef7b88 100755 --- a/oem-reownership/oem.example +++ b/oem-reownership/oem.example @@ -18,4 +18,4 @@ gpg_factory_resetted tpm_reowned #Once all stages are done, the Wizard removes /boot/oem, and ensures that /boot file checksum file is generated and signed with oem_gpg_User_PIN. # -#Then the wizard finally launches the selection of a new boot default, and asks the user if he wants to modifie the disk and if he wants to define a Disk Unlock Key. In such case, oem_TPM_Owner_Password is used to seal a new TOTP secret, oem_gpg_Admin_PIN is used to seal a new HOTP secret, and oem_gpg_User_PIN is used to sign configuration files checksums that changed under /boot. +#Then the wizard finally launches the selection of a new boot default, and asks the user if he wants to modify the disk and if he wants to define a Disk Unlock Key. In such case, oem_TPM_Owner_Password is used to seal a new TOTP secret, oem_gpg_Admin_PIN is used to seal a new HOTP secret, and oem_gpg_User_PIN is used to sign configuration files checksums that changed under /boot. From f5271913c76bc7886fc6d7b722115c1fa6587317 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Fri, 26 Apr 2019 12:48:42 -0400 Subject: [PATCH 12/91] Modify kexec-save-default to propose LUKS sealing of Disk Unlock Key only when board "CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY=y" is defined --- boards/x230/x230.config | 2 ++ initrd/bin/kexec-save-default | 6 +++--- initrd/etc/functions | 14 ++++++++------ 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/boards/x230/x230.config b/boards/x230/x230.config index 0d593e1fc..8f65d66c4 100644 --- a/boards/x230/x230.config +++ b/boards/x230/x230.config @@ -27,6 +27,8 @@ CONFIG_LINUX_USB=y CONFIG_LINUX_E1000E=y export CONFIG_TPM=y +#export CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY=y + export CONFIG_BOOTSCRIPT=/bin/gui-init export CONFIG_BOOT_REQ_HASH=n export CONFIG_BOOT_REQ_ROLLBACK=n diff --git a/initrd/bin/kexec-save-default b/initrd/bin/kexec-save-default index 4e9b186e4..596ef6e19 100755 --- a/initrd/bin/kexec-save-default +++ b/initrd/bin/kexec-save-default @@ -65,7 +65,7 @@ if [ "$num_lvm" -gt 1 ]; then fi };done elif [ "$num_lvm" -eq 1 ]; then - echo "Single Encrypted LVM group found at $lvm_suggest. Using it." + echo "Single Encrypted LVM group found at $lvm_suggest." lvm_volume_group=$lvm_suggest else echo "No encrypted LVM Group found." @@ -85,7 +85,7 @@ if [ "$num_devices" -gt 1 ]; then fi };done elif [ "$num_devices" -eq 1 ]; then - echo "Single Encrypted Disk found at $devices_suggest. Using it." + echo "Single Encrypted Disk found at $devices_suggest." key_devices=$devices_suggest else echo "No encrypted devices found." @@ -105,7 +105,7 @@ KEY_DEVICES="$paramsdir/kexec_key_devices.txt" KEY_LVM="$paramsdir/kexec_key_lvm.txt" save_key="n" -if [ "$CONFIG_TPM" = "y" ]; then +if [ "$CONFIG_TPM" = "y" ] && [ "$CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY" = "y" ]; then if [ ! -s "$KEY_DEVICES" ]; then read \ -n 1 \ diff --git a/initrd/etc/functions b/initrd/etc/functions index 53f743e07..097370167 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -431,14 +431,16 @@ check_onboarding_progress() mount -o remount,ro /boot unset totp_confirm unset reownership_state - whiptail --title 'DISK UNLOCK KEY ADVICE 1/3' --msgbox \ - "***You SHOULD SET a new Disk Unlock Key for your own data privacy!!!***\n\nDoing so, a witness will only be able to type observed Disk Unlock\n Key passphrase from this computer and won't be able on a cloned\n copy of this disk.\n\nThe release of Disk Unlock Key happens ONLY if TPM attests firmware\nintegrity, and only if Disk Unlock Key passphrase is valid.\n\nPlease hit Enter to continue" 30 60 + if [ "$CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY" = "y" ]; then + whiptail --title 'DISK UNLOCK KEY ADVICE 1/3' --msgbox \ + "***You SHOULD SET a new Disk Unlock Key for your own data privacy!!!***\n\nDoing so, a witness will only be able to type observed Disk Unlock\n Key passphrase from this computer and won't be able on a cloned\n copy of this disk.\n\nThe release of Disk Unlock Key happens ONLY if TPM attests firmware\nintegrity, and only if Disk Unlock Key passphrase is valid.\n\nPlease hit Enter to continue" 30 60 - whiptail --title 'DISK UNLOCK KEY ADVICE 2/3' --msgbox \ - "Otherwise, typing your Disk Recovery Key passphrase at boot puts you\nat risk. Someone could clone your disk and type that witnessed\npassphrase and access your data both locally and from a cloned\ndisk.\n\nCoupled with a strong passphrase, this improves your data privacy.\nCONSIDER YOURSELF WARNED.\n\nPlease hit Enter to continue" 30 60 + whiptail --title 'DISK UNLOCK KEY ADVICE 2/3' --msgbox \ + "Otherwise, typing your Disk Recovery Key passphrase at boot puts you\nat risk. Someone could clone your disk and type that witnessed\npassphrase and access your data both locally and from a cloned\ndisk.\n\nCoupled with a strong passphrase, this improves your data privacy.\nCONSIDER YOURSELF WARNED.\n\nPlease hit Enter to continue" 30 60 - whiptail --title 'DISK UNLOCK KEY ADVICE 3/3' --msgbox \ - "To set Disk Unlock Key, released by the TPM only if firmware integrity\n is attested:\n\nSelect from Main menu:\n\nAdvanced Options menu -> Other Boot Options -> Show OS boot menu\n1-Then select the first boot option proposed (dynamic option)\n2-Then,answer Y when asked to add Disk Unlock Key to the TPM.\n\nYou will be prompted to set one in the following steps.\n\nPlease hit Enter to continue" 30 60 + whiptail --title 'DISK UNLOCK KEY ADVICE 3/3' --msgbox \ + "To set Disk Unlock Key, released by the TPM only if firmware integrity\n is attested:\n\nSelect from Main menu:\n\nAdvanced Options menu -> Other Boot Options -> Show OS boot menu\n1-Then select the first boot option proposed (dynamic option)\n2-Then,answer Y when asked to add Disk Unlock Key to the TPM.\n\nYou will be prompted to set one in the following steps.\n\nPlease hit Enter to continue" 30 60 + fi return else #Deal with corner case where after inserting key in previous step, HOTP seal fails with provided good password. From 54a067c82efe51aaec9259fbe0388988fd7ccafa Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Fri, 26 Apr 2019 12:57:53 -0400 Subject: [PATCH 13/91] Setting proper defaults for boards specifying CONFIG_TPM=y in regard of CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY The librem boards defaults to CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY=n since they rely on LUKS being released with GPG QubesOS will support that feature when dom0 will be bumped to version 29, since cryptsetup needs to be upgraded to support that. --- boards/librem13v2/librem13v2.config | 3 +++ boards/librem13v4/librem13v4.config | 2 ++ boards/librem15v4/librem15v4.config | 2 ++ boards/x220/x220.config | 4 +++- boards/x230/x230.config | 2 +- 5 files changed, 11 insertions(+), 2 deletions(-) diff --git a/boards/librem13v2/librem13v2.config b/boards/librem13v2/librem13v2.config index eca005831..6e13c98ea 100644 --- a/boards/librem13v2/librem13v2.config +++ b/boards/librem13v2/librem13v2.config @@ -25,6 +25,9 @@ CONFIG_LIBREMKEY=y CONFIG_LINUX_USB=y export CONFIG_TPM=y +export CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY=n + +export CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY=y export CONFIG_BOOTSCRIPT=/bin/gui-init export CONFIG_BOOT_REQ_HASH=n export CONFIG_BOOT_REQ_ROLLBACK=n diff --git a/boards/librem13v4/librem13v4.config b/boards/librem13v4/librem13v4.config index 12fe04886..fb02c1dcc 100644 --- a/boards/librem13v4/librem13v4.config +++ b/boards/librem13v4/librem13v4.config @@ -25,6 +25,8 @@ CONFIG_LIBREMKEY=y CONFIG_LINUX_USB=y export CONFIG_TPM=y +export CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY=n + export CONFIG_BOOTSCRIPT=/bin/gui-init export CONFIG_BOOT_REQ_HASH=n export CONFIG_BOOT_REQ_ROLLBACK=n diff --git a/boards/librem15v4/librem15v4.config b/boards/librem15v4/librem15v4.config index 38041122e..a09c4e184 100644 --- a/boards/librem15v4/librem15v4.config +++ b/boards/librem15v4/librem15v4.config @@ -27,6 +27,8 @@ CONFIG_LIBREMKEY=y CONFIG_LINUX_USB=y export CONFIG_TPM=y +export CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY=n + export CONFIG_BOOTSCRIPT=/bin/gui-init export CONFIG_BOOT_REQ_HASH=n export CONFIG_BOOT_REQ_ROLLBACK=n diff --git a/boards/x220/x220.config b/boards/x220/x220.config index 0b901bdba..258782b1a 100644 --- a/boards/x220/x220.config +++ b/boards/x220/x220.config @@ -20,8 +20,10 @@ CONFIG_DROPBEAR=y CONFIG_LINUX_USB=y CONFIG_LINUX_E1000E=y -export CONFIG_BOOTSCRIPT=/bin/generic-init export CONFIG_TPM=y +export CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY=y + +export CONFIG_BOOTSCRIPT=/bin/generic-init export CONFIG_BOOT_REQ_HASH=n export CONFIG_BOOT_REQ_ROLLBACK=n export CONFIG_BOOT_KERNEL_ADD="intel_iommu=on" diff --git a/boards/x230/x230.config b/boards/x230/x230.config index 8f65d66c4..d2f8a8aee 100644 --- a/boards/x230/x230.config +++ b/boards/x230/x230.config @@ -27,7 +27,7 @@ CONFIG_LINUX_USB=y CONFIG_LINUX_E1000E=y export CONFIG_TPM=y -#export CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY=y +export CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY=y export CONFIG_BOOTSCRIPT=/bin/gui-init export CONFIG_BOOT_REQ_HASH=n From a5624f054cf9a9c4d10aaa7338cd768676b7342b Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Fri, 26 Apr 2019 13:10:44 -0400 Subject: [PATCH 14/91] Modified gitlab-ci.yaml so that the cache is shared only on the same branch to protect them from being corrupted between boards. --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ac691c8ee..107e74582 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -8,6 +8,7 @@ build: cache: paths: - ./ + key: "$CI_COMMIT_REF_SLUG" cache: untracked: true paths: From 677f81047551e6ad72333d436dca560b5550b9f2 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Fri, 26 Apr 2019 14:45:39 -0400 Subject: [PATCH 15/91] Fix regression that broke support for unencrypted partitions. UNTESTED. The default code path should still works if no encrypted partition is found --- initrd/bin/kexec-save-default | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/initrd/bin/kexec-save-default b/initrd/bin/kexec-save-default index 596ef6e19..a4c45fc0b 100755 --- a/initrd/bin/kexec-save-default +++ b/initrd/bin/kexec-save-default @@ -91,6 +91,10 @@ else echo "No encrypted devices found." fi +if [ "$num_lvm" -eq 0 ] && [ "$num_devices" -eq 0 ] + #No encrypted partition found. + no_encrypted_partition=1 +fi if [ ! -r "$TMP_MENU_FILE" ]; then die "No menu options available, please run kexec-select-boot" @@ -105,7 +109,8 @@ KEY_DEVICES="$paramsdir/kexec_key_devices.txt" KEY_LVM="$paramsdir/kexec_key_lvm.txt" save_key="n" -if [ "$CONFIG_TPM" = "y" ] && [ "$CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY" = "y" ]; then +if [ "$CONFIG_TPM" = "y" ] && [ "$CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY" = "y" ] && [ "$no_encrypted_partition" != "1" ]; then + #Go forward and propose to seal Disk Unlock Key with TPM only if at least a disk encrypted partition was found. if [ ! -s "$KEY_DEVICES" ]; then read \ -n 1 \ From 2c475b588527978de50e5088527b2ffebb251616 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Fri, 26 Apr 2019 19:04:07 -0400 Subject: [PATCH 16/91] .gitlab-ci.yml ./.git ignore --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 107e74582..25b848e43 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -12,7 +12,7 @@ build: cache: untracked: true paths: - - ./git + - ./.git script: - make BOARD=x230-flash - make BOARD=x230 From 49d264140c3c449a24d929a9f9265fde40aa304f Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sat, 27 Apr 2019 10:50:17 -0400 Subject: [PATCH 17/91] gpg-gui: Factory Reset Nitrokey Pro v2/Librem Key GPG Card -> Factory Reset Librem Key/Nitrokey Pro v2 GPG Card + keygen + flash --- initrd/bin/gpg-gui.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/initrd/bin/gpg-gui.sh b/initrd/bin/gpg-gui.sh index 1ca045a33..fb6e2f7b5 100755 --- a/initrd/bin/gpg-gui.sh +++ b/initrd/bin/gpg-gui.sh @@ -31,7 +31,7 @@ while true; do 'a' ' Add GPG key to standalone BIOS image + flash' \ 'l' ' List GPG keys in your keyring' \ 'g' ' Generate GPG keys on a USB security token' \ - 'F' ' Factory Reset Nitrokey Pro v2/Librem Key GPG Card' \ + 'F' ' Factory Reset Librem Key/Nitrokey Pro v2 GPG Card + keygen + flash' \ 'x' ' Exit' \ 2>/tmp/whiptail || recovery "GUI menu failed" From ab28f31ce04c4afbf58e39a9ceca6a91003c3c74 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Mon, 29 Apr 2019 22:43:09 -0400 Subject: [PATCH 18/91] kexec-save-default: corrections to properly support unencrypted installation. Tested on Fedrora-30 --- initrd/bin/kexec-save-default | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/initrd/bin/kexec-save-default b/initrd/bin/kexec-save-default index a4c45fc0b..730da17d6 100755 --- a/initrd/bin/kexec-save-default +++ b/initrd/bin/kexec-save-default @@ -35,7 +35,7 @@ HASH_FILE="$paramsdir/kexec_default_hashes.txt" lvm_suggest=$(lvm vgscan|awk -F '"' {'print $1'}|tail -n +2) -num_lvm=$(echo "$lvm_suggest"|wc -l) +num_lvm=$(echo -n "$lvm_suggest"|wc -l) if [ "$num_lvm" -eq 1 ] && [ -n "$lvm_suggest" ]; then lvm_volume_group=$lvm_suggest elif [ -z "$lvm_suggest" ]; then @@ -43,8 +43,8 @@ elif [ -z "$lvm_suggest" ]; then fi devices_suggest=$(blkid | cut -d ':' -f 1 | while read device;do cryptsetup isLuks "$device";if [ $(echo $?) == 0 ]; then echo "$device";fi; done | sort) -num_devices=$(echo "$devices_suggest"|wc -l) -if [ "$num_devices" -eq 1 ]; then +num_devices=$(echo -n "$devices_suggest"|wc -l) +if [ "$num_devices" -eq 1 ] && [ -s "$devices_suggest" ]; then key_devices=$devices_suggest else devices_suggest=$(echo $devices_suggest) @@ -64,7 +64,7 @@ if [ "$num_lvm" -gt 1 ]; then selected_lvmdev_not_existing=0 fi };done -elif [ "$num_lvm" -eq 1 ]; then +elif [ "$num_lvm" -eq 1 ] && [ -s $lvm_suggest ]; then echo "Single Encrypted LVM group found at $lvm_suggest." lvm_volume_group=$lvm_suggest else @@ -91,7 +91,7 @@ else echo "No encrypted devices found." fi -if [ "$num_lvm" -eq 0 ] && [ "$num_devices" -eq 0 ] +if [ "$num_lvm" -eq 0 ] && [ "$num_devices" -eq 0 ]; then #No encrypted partition found. no_encrypted_partition=1 fi From f89fca5e2e1c2591d8358aa4525c122fd806486c Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Mon, 29 Apr 2019 22:45:46 -0400 Subject: [PATCH 19/91] mount-usb: readd support of mounting second device wihtout new usb detection logic first, so that docking station device can be used to boot through boot from usb, which depends on mount-usb --- initrd/bin/mount-usb | 148 ++++++++++++++++++++++--------------------- 1 file changed, 76 insertions(+), 72 deletions(-) diff --git a/initrd/bin/mount-usb b/initrd/bin/mount-usb index 0886a31f0..0eecce494 100755 --- a/initrd/bin/mount-usb +++ b/initrd/bin/mount-usb @@ -25,92 +25,96 @@ if [ ! -d /media ]; then mkdir /media fi -stat -c %N /sys/block/sd* | grep usb | cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" > /tmp/usb_block_devices -if [ -z `cat /tmp/usb_block_devices` ]; then - if [ -x /bin/whiptail ]; then - whiptail --title 'USB Drive Missing' \ - --msgbox "Insert your USB drive and press Enter to continue." 16 60 - else - echo "+++ USB Drive Missing! Insert your USB drive and press Enter to continue." - read - fi - sleep 1 +#In case CONFIG_USB_BOOT_DEV was just a secondary device, attempt to mount it prior to search for it. +mount $CONFIG_USB_BOOT_DEV /media || MOUNT_CONFIG_USB_BOOT_DEV_FAILED=1 +if [ $MOUNT_CONFIG_USB_BOOT_DEV_FAILED -eq 1 ]; then stat -c %N /sys/block/sd* | grep usb | cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" > /tmp/usb_block_devices if [ -z `cat /tmp/usb_block_devices` ]; then if [ -x /bin/whiptail ]; then - whiptail $CONFIG_ERROR_BG_COLOR --title 'ERROR: USB Drive Missing' \ - --msgbox "USB Drive Missing! Aborting mount attempt.\n\nPress Enter to continue." 16 60 + whiptail --title 'USB Drive Missing' \ + --msgbox "Insert your USB drive and press Enter to continue." 16 60 else - echo "!!! ERROR: USB Drive Missing! Aborting mount. Press Enter to continue." + echo "+++ USB Drive Missing! Insert your USB drive and press Enter to continue." + read + fi + sleep 1 + stat -c %N /sys/block/sd* | grep usb | cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" > /tmp/usb_block_devices + if [ -z `cat /tmp/usb_block_devices` ]; then + if [ -x /bin/whiptail ]; then + whiptail $CONFIG_ERROR_BG_COLOR --title 'ERROR: USB Drive Missing' \ + --msgbox "USB Drive Missing! Aborting mount attempt.\n\nPress Enter to continue." 16 60 + else + echo "!!! ERROR: USB Drive Missing! Aborting mount. Press Enter to continue." + fi + exit 1 fi - exit 1 fi -fi -USB_MOUNT_DEVICE="" -# Check for the common case: a single USB disk with one partition -if [ `cat /tmp/usb_block_devices | wc -l` -eq 1 ]; then - USB_BLOCK_DEVICE=`cat /tmp/usb_block_devices` - # Subtract out block device - let USB_NUM_PARTITIONS=`ls -1 ${USB_BLOCK_DEVICE}* | wc -l`-1 - if [ ${USB_NUM_PARTITIONS} -eq 0 ]; then - USB_MOUNT_DEVICE=${USB_BLOCK_DEVICE} - elif [ ${USB_NUM_PARTITIONS} -eq 1 ]; then - USB_MOUNT_DEVICE=`ls -1 ${USB_BLOCK_DEVICE}* | tail -n1` - fi -fi -# otherwise, let the user pick -if [ -z ${USB_MOUNT_DEVICE} ]; then - > /tmp/usb_disk_list - for i in `cat /tmp/usb_block_devices`; do - # remove block device from list if numeric partitions exist, since not bootable - let USB_NUM_PARTITIONS=`ls -1 $i* | wc -l`-1 + USB_MOUNT_DEVICE="" + # Check for the common case: a single USB disk with one partition + if [ `cat /tmp/usb_block_devices | wc -l` -eq 1 ]; then + USB_BLOCK_DEVICE=`cat /tmp/usb_block_devices` + # Subtract out block device + let USB_NUM_PARTITIONS=`ls -1 ${USB_BLOCK_DEVICE}* | wc -l`-1 if [ ${USB_NUM_PARTITIONS} -eq 0 ]; then - echo $i >> /tmp/usb_disk_list - else - ls $i* | tail -${USB_NUM_PARTITIONS} >> /tmp/usb_disk_list + USB_MOUNT_DEVICE=${USB_BLOCK_DEVICE} + elif [ ${USB_NUM_PARTITIONS} -eq 1 ]; then + USB_MOUNT_DEVICE=`ls -1 ${USB_BLOCK_DEVICE}* | tail -n1` fi - done + fi + # otherwise, let the user pick + if [ -z ${USB_MOUNT_DEVICE} ]; then + > /tmp/usb_disk_list + for i in `cat /tmp/usb_block_devices`; do + # remove block device from list if numeric partitions exist, since not bootable + let USB_NUM_PARTITIONS=`ls -1 $i* | wc -l`-1 + if [ ${USB_NUM_PARTITIONS} -eq 0 ]; then + echo $i >> /tmp/usb_disk_list + else + ls $i* | tail -${USB_NUM_PARTITIONS} >> /tmp/usb_disk_list + fi + done - if [ -x /bin/whiptail ]; then - MENU_OPTIONS="" - n=0 - while read option - do - n=`expr $n + 1` - option=$(echo $option | tr " " "_") - MENU_OPTIONS="$MENU_OPTIONS $n ${option}" - done < /tmp/usb_disk_list + if [ -x /bin/whiptail ]; then + MENU_OPTIONS="" + n=0 + while read option + do + n=`expr $n + 1` + option=$(echo $option | tr " " "_") + MENU_OPTIONS="$MENU_OPTIONS $n ${option}" + done < /tmp/usb_disk_list - MENU_OPTIONS="$MENU_OPTIONS a Abort" - whiptail --clear --title "Select your USB disk" \ - --menu "Choose your USB disk [1-$n, a to abort]:" 20 120 8 \ - -- $MENU_OPTIONS \ - 2>/tmp/whiptail + MENU_OPTIONS="$MENU_OPTIONS a Abort" + whiptail --clear --title "Select your USB disk" \ + --menu "Choose your USB disk [1-$n, a to abort]:" 20 120 8 \ + -- $MENU_OPTIONS \ + 2>/tmp/whiptail - option_index=$(cat /tmp/whiptail) - else - echo "+++ Select your USB disk:" - n=0 - while read option - do - n=`expr $n + 1` - echo "$n. $option" - done < /tmp/usb_disk_list + option_index=$(cat /tmp/whiptail) + else + echo "+++ Select your USB disk:" + n=0 + while read option + do + n=`expr $n + 1` + echo "$n. $option" + done < /tmp/usb_disk_list - read \ - -p "Choose your USB disk [1-$n, a to abort]: " \ - option_index - fi + read \ + -p "Choose your USB disk [1-$n, a to abort]: " \ + option_index + fi - if [ "$option_index" = "a" ]; then - exit 1 + if [ "$option_index" = "a" ]; then + exit 1 + fi + USB_MOUNT_DEVICE=`head -n $option_index /tmp/usb_disk_list | tail -1` fi - USB_MOUNT_DEVICE=`head -n $option_index /tmp/usb_disk_list | tail -1` -fi -if [ "$1" = "rw" ]; then - mount -o rw $USB_MOUNT_DEVICE /media -else - mount -o ro $USB_MOUNT_DEVICE /media + if [ "$1" = "rw" ]; then + mount -o rw $USB_MOUNT_DEVICE /media + else + mount -o ro $USB_MOUNT_DEVICE /media + fi fi From f716fd3542a9eae32af52ba0010791627627b74f Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Wed, 1 May 2019 13:05:55 -0400 Subject: [PATCH 20/91] initrd/bin/reencrypt-luks: - logic was invalid on checking into checking result of cryptsetup calls. - Cleaning OEM parts where no encrypted devices are found, skipping the reencryption and password change of container --- initrd/bin/reencrypt-luks | 88 +++++++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 37 deletions(-) diff --git a/initrd/bin/reencrypt-luks b/initrd/bin/reencrypt-luks index e74af8ea2..0390bac57 100755 --- a/initrd/bin/reencrypt-luks +++ b/initrd/bin/reencrypt-luks @@ -10,21 +10,34 @@ select_luks_container() LUKS=$(cut -d ' ' -f1 /boot/kexec_key_devices.txt) else #generate a list of devices to choose from that contain a LUKS header - blkid | cut -d ':' -f 1 | while read device;do cryptsetup isLuks $device;if [ $(echo $?) == 0 ]; then echo $device;fi; done | sort > /tmp/luks_devices.txt + lvm vgscan||true + blkid | cut -d ':' -f 1 | while read device;do cryptsetup isLuks $device;if [ $(echo $?) == 0 ]; then echo $device;fi; done | sort > /tmp/luks_devices.txt + if [ $(cat /tmp/luks_devices.txt | wc -l) -gt 0 ]; then file_selector "/tmp/luks_devices.txt" "Select LUKS container device" - if [ "$FILE" == "" ]; then - return + if [ "$FILE" == "" ]; then + return + else + LUKS=$FILE + mount_boot + mount -o remount,rw /boot + echo "$LUKS $(cryptsetup luksUUID $LUKS)" > /boot/kexec_key_devices.txt + mount -o remount,ro /boot + fi else - LUKS=$FILE - mount_boot - mount -o remount,rw /boot - echo "$LUKS $(cryptsetup luksUUID $LUKS)" > /boot/kexec_key_devices.txt - mount -o remount,ro /boot + #There is no LUKS device, we skip LUKS reencryption process in OEM reownership wizard + if [ -e /boot/oem ];then + mount -o remount,rw /boot + echo "luks_reencrypted" >> /boot/oem + echo "luks_passwd_changed" >> /boot/oem + unset reownership_state + mount -o remount,ro /boot + fi + die "No encrypted device found." fi fi } -if [ $reownership_state = "luks_reencryption" ]; then +if [ -n "$reownership_state" ] && [ "$reownership_state" = "luks_reencryption" ]; then #if no USB oem-privisioning file provides actual Disk Recovery Key if [ -z "$oem_luks_actual_Disk_Recovery_Key" ]; then whiptail --title 'Reencrypt actual LUKS container with a new user selected strong passphrase?' \ @@ -38,26 +51,27 @@ if [ $reownership_state = "luks_reencryption" ]; then echo -n "$oem_luks_actual_Disk_Recovery_Key" > /tmp/oem_luks_actual_Disk_Recovery_Key select_luks_container cryptsetup-reencrypt -B 32 --use-directio "$LUKS" --key-slot 0 --key-file /tmp/oem_luks_actual_Disk_Recovery_Key -h sha256 - fi - if [ $(echo $?) -ne 0 ]; then - whiptail --title 'Invalid LUKS Disk Recovery Key passphrase?' --msgbox \ - "The LUKS Disk Recovery Key password 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.\n\nTo do so, place ISO file and its signature file on root of USB drive,\n and select Boot from USB\n\nHit Enter to continue." 30 60 - shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null - continue - else - #Successfully reencrypted LUKS container with current Disk Recovery Key passphrase. Write successful state in oem file - if [ -e /boot/oem ];then - mount -o remount,rw /boot - echo "luks_reencrypted" >> /boot/oem - reownership_state="luks_password_change" - mount -o remount,ro /boot + if [ $(echo $?) -ne 0 ]; then + whiptail --title 'Invalid LUKS Disk Recovery Key passphrase?' --msgbox \ + "The LUKS Disk Recovery Key password 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.\n\nTo do so, place ISO file and its signature file on root of USB drive,\n and select Boot from USB\n\nHit Enter to continue." 30 60 shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null + unset oem_luks_actual_Disk_Recovery_Key + continue + else + #Successfully reencrypted LUKS container with current Disk Recovery Key passphrase. Write successful state in oem file + if [ -e /boot/oem ];then + mount -o remount,rw /boot + echo "luks_reencrypted" >> /boot/oem + reownership_state="luks_password_change" + mount -o remount,ro /boot + shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null + fi fi - fi continue + fi fi -if [ $reownership_state == "luks_password_change" ]; then +if [ -n "$reownership_state" ] && [ "$reownership_state" = "luks_password_change" ]; then #if actual or new Disk Recovery Key is not provisioned by USB oem-provisioning file if [ -z "$oem_luks_actual_Disk_Recovery_Key" ] || [ -z "$oem_luks_new_Disk_Recovery_Key" ] ; then whiptail --title 'Changing LUKS Disk Recovery Key passphrase' --msgbox \ @@ -72,21 +86,21 @@ if [ $reownership_state == "luks_password_change" ]; then echo -n "$oem_luks_new_Disk_Recovery_Key" > /tmp/oem_luks_new_Disk_Recovery_Key echo -n "$oem_luks_actual_Disk_Recovery_Key" > /tmp/oem_luks_actual_Disk_Recovery_Key cryptsetup luksChangeKey "$LUKS" --key-slot 0 --key-file=/tmp/oem_luks_actual_Disk_Recovery_Key /tmp/oem_luks_new_Disk_Recovery_Key - fi - if [ $(echo $?) -ne 0 ]; then - 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 - shred -n 10 -z -u /tmp/oem_luks_new_Disk_Recovery_Key 2> /dev/null - shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null - continue - else - #Successfully changed LUKS Disk Recovery Key passphrase. Write successful state in oem file - if [ -e /boot/oem ];then - mount -o remount,rw /boot - echo "luks_passwd_changed" >> /boot/oem - mount -o remount,ro /boot + if [ $(echo $?) -ne 0 ]; then + 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 shred -n 10 -z -u /tmp/oem_luks_new_Disk_Recovery_Key 2> /dev/null shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null + continue + else + #Successfully changed LUKS Disk Recovery Key passphrase. Write successful state in oem file + if [ -e /boot/oem ];then + mount -o remount,rw /boot + echo "luks_passwd_changed" >> /boot/oem + mount -o remount,ro /boot + shred -n 10 -z -u /tmp/oem_luks_new_Disk_Recovery_Key 2> /dev/null + shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null + fi fi fi continue From 49405939bd18d2bfc7120fa16880fd75ee86ae55 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Wed, 1 May 2019 15:38:29 -0400 Subject: [PATCH 21/91] Revert "Support Fedora 30 boot configuration" This reverts commit bc5343c626fed8dd43b512f2a2cedcfddfcfe7c8. --- initrd/bin/kexec-parse-bls | 94 ------------------------------------ initrd/bin/kexec-select-boot | 5 -- 2 files changed, 99 deletions(-) delete mode 100755 initrd/bin/kexec-parse-bls diff --git a/initrd/bin/kexec-parse-bls b/initrd/bin/kexec-parse-bls deleted file mode 100755 index 70a071a22..000000000 --- a/initrd/bin/kexec-parse-bls +++ /dev/null @@ -1,94 +0,0 @@ -#!/bin/sh -set -e -o pipefail -bootdir="$1" -file="$2" -blsdir="$3" - -if [ -z "$bootdir" -o -z "$file" ]; then - die "Usage: $0 /boot /boot/grub/grub.cfg blsdir" -fi - -reset_entry() { - name="" - kexectype="elf" - kernel="" - initrd="" - modules="" - append="$dfltappend" -} - -filedir=`dirname $file` -bootdir="${bootdir%%/}" -bootlen="${#bootdir}" -appenddir="${filedir:$bootlen}" -# assumption. grubenv is in same location as config file -# ignored if doesn't exist -grubenv="$filedir/grubenv" - -fix_path() { - path="$@" - if [ "${path:0:1}" != "/" ]; then - path="$appenddir/$path" - fi -} - -echo_entry() { - if [ "$kexectype" = "elf" ]; then - if [ -z "$kernel" ]; then return; fi - - fix_path $kernel - entry="$name|$kexectype|kernel $path" - if [ -n "$initrd" ]; then - fix_path $initrd - entry="$entry|initrd $path" - fi - if [ -n "$append" ]; then - entry="$entry|append $append" - fi - - echo $(eval "echo \"$entry\"") - fi - if [ "$kexectype" = "multiboot" -o "$kexectype" = "xen" ]; then - if [ -z "$kernel" ]; then return; fi - - fix_path $kernel - echo $(eval "echo \"$name|$kexectype|kernel $path$modules\"") - fi -} - -bls_entry() { - # add info to menuentry - trimcmd=`echo $line | tr '\t ' ' ' | tr -s ' '` - cmd=`echo $trimcmd | cut -d\ -f1` - val=`echo $trimcmd | cut -d\ -f2-` - case $cmd in - title) - name=$val - ;; - linux*) - kernel=$val - ;; - initrd*) - initrd=$val - ;; - options) - # default is "options $kernelopts", so need to substitute that variable set from grubenv - append=`echo "$val" | sed "s@\$kernelopts@$kernelopts@"` - ;; - esac -} - -# This is the default append value if no options field in bls entry -kernelopts=`grep "set default_kernelopts" "$file" | tr "'" "\"" | cut -d\" -f 2` -[ -f "$grubenv" ] && kernelopts=`grep "^kernelopts" "$grubenv" | tr '@' '_' | cut -d= -f 2-` -reset_entry -find $blsdir -type f -name \*.conf | -while read f -do - while read line - do - bls_entry - done < "$f" - echo_entry - reset_entry -done diff --git a/initrd/bin/kexec-select-boot b/initrd/bin/kexec-select-boot index 08c388427..93c270328 100755 --- a/initrd/bin/kexec-select-boot +++ b/initrd/bin/kexec-select-boot @@ -162,11 +162,6 @@ scan_options() { if [ -r $option_file ]; then rm $option_file; fi for i in `find $bootdir -name "$config"`; do kexec-parse-boot "$bootdir" "$i" >> $option_file - # FC29/30+ may use BLS format grub config files - # https://fedoraproject.org/wiki/Changes/BootLoaderSpecByDefault - if [ -d "$bootdir/loader/entries" ]; then - kexec-parse-bls "$bootdir" "$i" "$bootdir/loader/entries" >> $option_file - fi done if [ ! -r $option_file ]; then die "Failed to parse any boot options" From 81594fde61b017e914de56217ccfa8c214d0c7bf Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Wed, 1 May 2019 17:40:52 -0400 Subject: [PATCH 22/91] initrd/bin/kexec-save-default: Regression fix. --- initrd/bin/kexec-save-default | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/initrd/bin/kexec-save-default b/initrd/bin/kexec-save-default index 730da17d6..49e1cc382 100755 --- a/initrd/bin/kexec-save-default +++ b/initrd/bin/kexec-save-default @@ -35,7 +35,7 @@ HASH_FILE="$paramsdir/kexec_default_hashes.txt" lvm_suggest=$(lvm vgscan|awk -F '"' {'print $1'}|tail -n +2) -num_lvm=$(echo -n "$lvm_suggest"|wc -l) +num_lvm=$(echo "$lvm_suggest"|wc -l) if [ "$num_lvm" -eq 1 ] && [ -n "$lvm_suggest" ]; then lvm_volume_group=$lvm_suggest elif [ -z "$lvm_suggest" ]; then @@ -43,7 +43,7 @@ elif [ -z "$lvm_suggest" ]; then fi devices_suggest=$(blkid | cut -d ':' -f 1 | while read device;do cryptsetup isLuks "$device";if [ $(echo $?) == 0 ]; then echo "$device";fi; done | sort) -num_devices=$(echo -n "$devices_suggest"|wc -l) +num_devices=$(echo "$devices_suggest"|wc -l) if [ "$num_devices" -eq 1 ] && [ -s "$devices_suggest" ]; then key_devices=$devices_suggest else From 2fc2cc474d13357bbb7630c7b43345527bfb0a3f Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Thu, 2 May 2019 16:13:40 -0400 Subject: [PATCH 23/91] Add hash files related to roms put in artifact.zip and remove from build output --- .gitlab-ci.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 25b848e43..8887eb824 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -16,11 +16,9 @@ build: script: - make BOARD=x230-flash - make BOARD=x230 - - echo "x230-flash hashes:" - - cat ./build/x230-flash/hashes.txt - - echo "x230 hashes:" - - cat ./build/x230/hashes.txt artifacts: paths: - ./build/x230-flash/x230-flash.rom + - ./build/x230-flash/hashes.txt - ./build/x230/coreboot.rom + - ./build/x230/hashes.txt From 460186cf8b32e671f88fcec2dec291bd1c55a6b9 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Thu, 2 May 2019 16:24:27 -0400 Subject: [PATCH 24/91] .gitlab-ci.yaml: Actually, having the content of the rom hashes both on the build log and inside of the artifact makes more sense --- .gitlab-ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8887eb824..60254d045 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -16,6 +16,10 @@ build: script: - make BOARD=x230-flash - make BOARD=x230 + - echo "x230-flash hashes:" + - cat ./build/x230-flash/hashes.txt + - echo "x230 hashes:" + - cat ./build/x230/hashes.txt artifacts: paths: - ./build/x230-flash/x230-flash.rom From ce2d41479f2e878a8e97a1f35efc3fa4e750ec59 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Thu, 2 May 2019 16:40:53 -0400 Subject: [PATCH 25/91] Makefile: Required change to have distinct hash files for each board. Todo: Can't figure out to make coreboot.rom -> $(BOARD).rom .gitlab-ci.yml: Hashes are outputted both on build log and attached to artifacts. --- .gitlab-ci.yml | 4 ++-- Makefile | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 60254d045..42bc009af 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -23,6 +23,6 @@ build: artifacts: paths: - ./build/x230-flash/x230-flash.rom - - ./build/x230-flash/hashes.txt + - ./build/x230-flash/x230-flash-hashes.txt - ./build/x230/coreboot.rom - - ./build/x230/hashes.txt + - ./build/x230/x230-hashes.txt diff --git a/Makefile b/Makefile index 3cc193a32..9c714dd98 100644 --- a/Makefile +++ b/Makefile @@ -59,7 +59,7 @@ GIT_STATUS := $(shell \ fi) # record the build date / git hashes and other files here -HASHES := $(build)/$(BOARD)/hashes.txt +HASHES := $(build)/$(BOARD)/$(BOARD)-hashes.txt # Create the board output directory if it doesn't already exist BOARD_LOG := $(shell \ From 2e99b749436453b650674ccf789d445eceeb669e Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Thu, 2 May 2019 16:50:10 -0400 Subject: [PATCH 26/91] .gitlab-ci.yml: Remove .git uncaching --- .gitlab-ci.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 42bc009af..71940312b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,10 +9,6 @@ build: paths: - ./ key: "$CI_COMMIT_REF_SLUG" - cache: - untracked: true - paths: - - ./.git script: - make BOARD=x230-flash - make BOARD=x230 From 7a24dae3497d5e9cd59a9c78662543846130a598 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Thu, 2 May 2019 19:25:52 -0400 Subject: [PATCH 27/91] .gitlab-ci.yml: forgot to rename the files to be outputed to build log accordingly --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 71940312b..8b8e1e0d6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -13,9 +13,9 @@ build: - make BOARD=x230-flash - make BOARD=x230 - echo "x230-flash hashes:" - - cat ./build/x230-flash/hashes.txt + - cat ./build/x230-flash/x230-flash-hashes.txt - echo "x230 hashes:" - - cat ./build/x230/hashes.txt + - cat ./build/x230/x230-hashes.txt artifacts: paths: - ./build/x230-flash/x230-flash.rom From 327b12a041683167088a18a8f22c903a2bb634ec Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Thu, 2 May 2019 21:02:45 -0400 Subject: [PATCH 28/91] Reverting .gitlab-ci.yml and Makefile to output on both build log and artifact, without changing the filename, since it could break other CIs. --- .gitlab-ci.yml | 8 ++++---- Makefile | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8b8e1e0d6..cf638b88b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -13,12 +13,12 @@ build: - make BOARD=x230-flash - make BOARD=x230 - echo "x230-flash hashes:" - - cat ./build/x230-flash/x230-flash-hashes.txt + - cat ./build/x230-flash/hashes.txt - echo "x230 hashes:" - - cat ./build/x230/x230-hashes.txt + - cat ./build/x230/hashes.txt artifacts: paths: - ./build/x230-flash/x230-flash.rom - - ./build/x230-flash/x230-flash-hashes.txt + - ./build/x230-flash/hashes.txt - ./build/x230/coreboot.rom - - ./build/x230/x230-hashes.txt + - ./build/x230/hashes.txt diff --git a/Makefile b/Makefile index 9c714dd98..3cc193a32 100644 --- a/Makefile +++ b/Makefile @@ -59,7 +59,7 @@ GIT_STATUS := $(shell \ fi) # record the build date / git hashes and other files here -HASHES := $(build)/$(BOARD)/$(BOARD)-hashes.txt +HASHES := $(build)/$(BOARD)/hashes.txt # Create the board output directory if it doesn't already exist BOARD_LOG := $(shell \ From 696980d8813a2b6dac248ad3c404947bd220c9a4 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Fri, 3 May 2019 10:31:56 -0400 Subject: [PATCH 29/91] initrd/etc/functions: pcrs to be shown are intended to be 0-8 as in master initrd/bin/kexec-insert-key: typo fix boards/librem13v2/librem13v2.config: remove duplicate of export --- boards/librem13v2/librem13v2.config | 1 - initrd/bin/kexec-insert-key | 2 +- initrd/etc/functions | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/boards/librem13v2/librem13v2.config b/boards/librem13v2/librem13v2.config index 6e13c98ea..130f36b09 100644 --- a/boards/librem13v2/librem13v2.config +++ b/boards/librem13v2/librem13v2.config @@ -27,7 +27,6 @@ CONFIG_LINUX_USB=y export CONFIG_TPM=y export CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY=n -export CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY=y export CONFIG_BOOTSCRIPT=/bin/gui-init export CONFIG_BOOT_REQ_HASH=n export CONFIG_BOOT_REQ_ROLLBACK=n diff --git a/initrd/bin/kexec-insert-key b/initrd/bin/kexec-insert-key index dde229d40..9081fcd87 100755 --- a/initrd/bin/kexec-insert-key +++ b/initrd/bin/kexec-insert-key @@ -26,7 +26,7 @@ if [ -r "$TMP_KEY_LVM" ]; then || die "$VOLUME_GROUP: Unable to activate volume group" fi -# Measure the LUKS headers before we unseal the Disk Unock Key +# Measure the LUKS headers before we unseal the Disk Unlock Key cat "$TMP_KEY_DEVICES" | cut -d\ -f1 | xargs /bin/qubes-measure-luks \ || die "LUKS measure failed" diff --git a/initrd/etc/functions b/initrd/etc/functions index 097370167..9dee82a4a 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -52,7 +52,7 @@ pause_recovery() { } pcrs() { - head -9 /sys/class/tpm/tpm0/pcrs + head -8 /sys/class/tpm/tpm0/pcrs } confirm_totp() From a937a752c8ff072166a44a46dd1f59589fffbf5f Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Fri, 3 May 2019 10:42:28 -0400 Subject: [PATCH 30/91] initrd/bin/tpm-reset: removal of whitespace --- initrd/bin/tpm-reset | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/initrd/bin/tpm-reset b/initrd/bin/tpm-reset index 150afbedb..7a929ba68 100755 --- a/initrd/bin/tpm-reset +++ b/initrd/bin/tpm-reset @@ -35,7 +35,7 @@ while [ "$key_password" != "$key_password2" ]; do tpm physicalpresence -s tpm physicalenable tpm physicalsetdeactivated -c -tpm forceclear +tpm forceclear tpm physicalenable tpm takeown -pwdo "$key_password" >/dev/null 2>&1 From ea52ca19b91d81b4bc24c0ae73500d147aa5f17b Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Fri, 3 May 2019 15:00:54 -0400 Subject: [PATCH 31/91] initrd/bin/reencrypt-luks: correct logic - Validated that unprovisioned worked (Didnt) - Validated the oem-privisioning works --- initrd/bin/reencrypt-luks | 65 +++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/initrd/bin/reencrypt-luks b/initrd/bin/reencrypt-luks index 0390bac57..bd127cb03 100755 --- a/initrd/bin/reencrypt-luks +++ b/initrd/bin/reencrypt-luks @@ -51,23 +51,27 @@ if [ -n "$reownership_state" ] && [ "$reownership_state" = "luks_reencryption" ] echo -n "$oem_luks_actual_Disk_Recovery_Key" > /tmp/oem_luks_actual_Disk_Recovery_Key select_luks_container cryptsetup-reencrypt -B 32 --use-directio "$LUKS" --key-slot 0 --key-file /tmp/oem_luks_actual_Disk_Recovery_Key -h sha256 - if [ $(echo $?) -ne 0 ]; then - whiptail --title 'Invalid LUKS Disk Recovery Key passphrase?' --msgbox \ - "The LUKS Disk Recovery Key password 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.\n\nTo do so, place ISO file and its signature file on root of USB drive,\n and select Boot from USB\n\nHit Enter to continue." 30 60 + #TODO: is -h sha256 required? + fi + + #Validate past cryptsetup attempts + if [ $(echo $?) -ne 0 ]; then + whiptail --title 'Invalid LUKS Disk Recovery Key passphrase?' --msgbox \ + "The LUKS Disk Recovery Key password 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.\n\nTo do so, place ISO file and its signature file on root of USB drive,\n and select Boot from USB\n\nHit Enter to continue." 30 60 + shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null + #unsetting oem_luks_actual_Disk_Recovery_Key will prompt user for Disk Recovery Key passphrase prompt on next round + unset oem_luks_actual_Disk_Recovery_Key + continue + else + #Successfully reencrypted LUKS container with current Disk Recovery Key passphrase. Write successful state in oem file + if [ -e /boot/oem ];then + mount -o remount,rw /boot + echo "luks_reencrypted" >> /boot/oem + reownership_state="luks_password_change" + mount -o remount,ro /boot shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null - unset oem_luks_actual_Disk_Recovery_Key - continue - else - #Successfully reencrypted LUKS container with current Disk Recovery Key passphrase. Write successful state in oem file - if [ -e /boot/oem ];then - mount -o remount,rw /boot - echo "luks_reencrypted" >> /boot/oem - reownership_state="luks_password_change" - mount -o remount,ro /boot - shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null - fi fi - continue + continue fi fi @@ -76,9 +80,7 @@ if [ -n "$reownership_state" ] && [ "$reownership_state" = "luks_password_change if [ -z "$oem_luks_actual_Disk_Recovery_Key" ] || [ -z "$oem_luks_new_Disk_Recovery_Key" ] ; then 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 - select_luks_container - cryptsetup luksChangeKey "$LUKS" --key-slot 0 --tries 3 else #if actual and new Disk Recovery Key is provisioned by USB oem-provisioning file @@ -86,21 +88,24 @@ if [ -n "$reownership_state" ] && [ "$reownership_state" = "luks_password_change echo -n "$oem_luks_new_Disk_Recovery_Key" > /tmp/oem_luks_new_Disk_Recovery_Key echo -n "$oem_luks_actual_Disk_Recovery_Key" > /tmp/oem_luks_actual_Disk_Recovery_Key cryptsetup luksChangeKey "$LUKS" --key-slot 0 --key-file=/tmp/oem_luks_actual_Disk_Recovery_Key /tmp/oem_luks_new_Disk_Recovery_Key - if [ $(echo $?) -ne 0 ]; then - 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 + fi + #Validate past cryptsetup attempts + if [ $(echo $?) -ne 0 ]; then + #Cryptsetup was unsuccessful + 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 + shred -n 10 -z -u /tmp/oem_luks_new_Disk_Recovery_Key 2> /dev/null + shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null + else + #Cryptsetup was successful + if [ -e /boot/oem ];then + mount -o remount,rw /boot + echo "luks_passwd_changed" >> /boot/oem + mount -o remount,ro /boot shred -n 10 -z -u /tmp/oem_luks_new_Disk_Recovery_Key 2> /dev/null shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null - continue - else - #Successfully changed LUKS Disk Recovery Key passphrase. Write successful state in oem file - if [ -e /boot/oem ];then - mount -o remount,rw /boot - echo "luks_passwd_changed" >> /boot/oem - mount -o remount,ro /boot - shred -n 10 -z -u /tmp/oem_luks_new_Disk_Recovery_Key 2> /dev/null - shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null - fi + unset oem_luks_actual_Disk_Recovery_Key + unset oem_luks_new_Disk_Recovery_Key fi fi continue From e4e8cb610157d73acbc537aa66a0c99cd854277c Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Fri, 3 May 2019 15:42:13 -0400 Subject: [PATCH 32/91] initrd/bin/reencrypt-luks remove static cipher that was put in place when debugging oem-provisioning provided secrets "-h sha256" --- initrd/bin/reencrypt-luks | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/initrd/bin/reencrypt-luks b/initrd/bin/reencrypt-luks index bd127cb03..27869dbf6 100755 --- a/initrd/bin/reencrypt-luks +++ b/initrd/bin/reencrypt-luks @@ -50,8 +50,7 @@ if [ -n "$reownership_state" ] && [ "$reownership_state" = "luks_reencryption" ] #USB "oem-privisioning" file provides actual Disk Recovery Key echo -n "$oem_luks_actual_Disk_Recovery_Key" > /tmp/oem_luks_actual_Disk_Recovery_Key select_luks_container - cryptsetup-reencrypt -B 32 --use-directio "$LUKS" --key-slot 0 --key-file /tmp/oem_luks_actual_Disk_Recovery_Key -h sha256 - #TODO: is -h sha256 required? + cryptsetup-reencrypt -B 32 --use-directio "$LUKS" --key-slot 0 --key-file /tmp/oem_luks_actual_Disk_Recovery_Key fi #Validate past cryptsetup attempts From 86e1c14840f4a4653afa7fe6a5771af8c94d0405 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Fri, 3 May 2019 15:50:07 -0400 Subject: [PATCH 33/91] .gitlab-ci.yml: Trying to get rid of .git cache warnings --- .gitlab-ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index cf638b88b..c715ab191 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,6 +5,10 @@ stages: build: stage: build + cache: + untracked: true + paths: + - ./git cache: paths: - ./ From ff0c33a30dbf1fe911eb09b47bac0e320e597b81 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sat, 4 May 2019 13:08:21 -0400 Subject: [PATCH 34/91] initrd/bin/mount-usb: Support for LUKS encrypted devices added. - Will attempt to mount board configured USB device first and fail silently - Will search for usb devices, prompt the user to select (As per Kyle's merged PR) - Will verify if partition is LUKS encrypted device. If it is, it will prompt for it's passphrase and replace USB device with luksOpened one before continuing normal mount operation --- initrd/bin/mount-usb | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/initrd/bin/mount-usb b/initrd/bin/mount-usb index 0eecce494..13f79fb44 100755 --- a/initrd/bin/mount-usb +++ b/initrd/bin/mount-usb @@ -2,6 +2,16 @@ # Mount a USB device . /etc/functions +is_Luks_luksOpen() +{ + cryptsetup isLuks $USB_MOUNT_DEVICE + if [ $(echo $?) == 0 ]; then + echo -e "USB Device $USB_MOUNT_DEVICE is encrypted.\n" + cryptsetup luksOpen $USB_MOUNT_DEVICE usbdev + USB_MOUNT_DEVICE="/dev/mapper/usbdev" + fi +} + enable_usb #OEM reownership, when attempting to load /media/oem-provisioning, @@ -26,7 +36,7 @@ if [ ! -d /media ]; then fi #In case CONFIG_USB_BOOT_DEV was just a secondary device, attempt to mount it prior to search for it. -mount $CONFIG_USB_BOOT_DEV /media || MOUNT_CONFIG_USB_BOOT_DEV_FAILED=1 +mount $CONFIG_USB_BOOT_DEV /media >/dev/null 2>&1|| MOUNT_CONFIG_USB_BOOT_DEV_FAILED=1 if [ $MOUNT_CONFIG_USB_BOOT_DEV_FAILED -eq 1 ]; then stat -c %N /sys/block/sd* | grep usb | cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" > /tmp/usb_block_devices if [ -z `cat /tmp/usb_block_devices` ]; then @@ -112,6 +122,8 @@ if [ $MOUNT_CONFIG_USB_BOOT_DEV_FAILED -eq 1 ]; then USB_MOUNT_DEVICE=`head -n $option_index /tmp/usb_disk_list | tail -1` fi + #Check if $USB_MOUNT_DEVICE is a LUKS encrypted device.Ff so, luksOpen it and replace $USB_MOUNT_DEVICE with /dev/mapper/usbdev + is_Luks_luksOpen if [ "$1" = "rw" ]; then mount -o rw $USB_MOUNT_DEVICE /media else From a9b2ec58043f4437dbdc68b2904c9ce7f2c7fb73 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sat, 4 May 2019 16:18:06 -0400 Subject: [PATCH 35/91] initrd/bin/mount-usb: add board CONFIG_USB_BOOT_DEV defined device in proposed list only if not USB. --- initrd/bin/mount-usb | 156 +++++++++++++++++++++---------------------- 1 file changed, 78 insertions(+), 78 deletions(-) diff --git a/initrd/bin/mount-usb b/initrd/bin/mount-usb index 13f79fb44..2c1849226 100755 --- a/initrd/bin/mount-usb +++ b/initrd/bin/mount-usb @@ -35,98 +35,98 @@ if [ ! -d /media ]; then mkdir /media fi -#In case CONFIG_USB_BOOT_DEV was just a secondary device, attempt to mount it prior to search for it. -mount $CONFIG_USB_BOOT_DEV /media >/dev/null 2>&1|| MOUNT_CONFIG_USB_BOOT_DEV_FAILED=1 -if [ $MOUNT_CONFIG_USB_BOOT_DEV_FAILED -eq 1 ]; then +stat -c %N /sys/block/sd* | grep usb | cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" > /tmp/usb_block_devices +#In case CONFIG_USB_BOOT_DEV was just a secondary device specified in board configuration and found, add it to the list +stat -c %N $CONFIG_USB_BOOT_DEV | grep -v usb| cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" >> /tmp/usb_block_devices +if [ -z `cat /tmp/usb_block_devices` ]; then + if [ -x /bin/whiptail ]; then + whiptail --title 'USB Drive Missing' \ + --msgbox "Insert your USB drive and press Enter to continue." 16 60 + else + echo "+++ USB Drive Missing! Insert your USB drive and press Enter to continue." + read + fi + sleep 1 stat -c %N /sys/block/sd* | grep usb | cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" > /tmp/usb_block_devices + #In case CONFIG_USB_BOOT_DEV was just a secondary device specified in board configuration and found, add it to the list + stat -c %N $CONFIG_USB_BOOT_DEV | grep -v usb| cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" >> /tmp/usb_block_devices if [ -z `cat /tmp/usb_block_devices` ]; then if [ -x /bin/whiptail ]; then - whiptail --title 'USB Drive Missing' \ - --msgbox "Insert your USB drive and press Enter to continue." 16 60 + whiptail $CONFIG_ERROR_BG_COLOR --title 'ERROR: USB Drive Missing' \ + --msgbox "USB Drive Missing! Aborting mount attempt.\n\nPress Enter to continue." 16 60 else - echo "+++ USB Drive Missing! Insert your USB drive and press Enter to continue." - read - fi - sleep 1 - stat -c %N /sys/block/sd* | grep usb | cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" > /tmp/usb_block_devices - if [ -z `cat /tmp/usb_block_devices` ]; then - if [ -x /bin/whiptail ]; then - whiptail $CONFIG_ERROR_BG_COLOR --title 'ERROR: USB Drive Missing' \ - --msgbox "USB Drive Missing! Aborting mount attempt.\n\nPress Enter to continue." 16 60 - else - echo "!!! ERROR: USB Drive Missing! Aborting mount. Press Enter to continue." - fi - exit 1 + echo "!!! ERROR: USB Drive Missing! Aborting mount. Press Enter to continue." fi + exit 1 fi +fi - USB_MOUNT_DEVICE="" - # Check for the common case: a single USB disk with one partition - if [ `cat /tmp/usb_block_devices | wc -l` -eq 1 ]; then - USB_BLOCK_DEVICE=`cat /tmp/usb_block_devices` - # Subtract out block device - let USB_NUM_PARTITIONS=`ls -1 ${USB_BLOCK_DEVICE}* | wc -l`-1 +USB_MOUNT_DEVICE="" +# Check for the common case: a single USB disk with one partition +if [ `cat /tmp/usb_block_devices | wc -l` -eq 1 ]; then + USB_BLOCK_DEVICE=`cat /tmp/usb_block_devices` + # Subtract out block device + let USB_NUM_PARTITIONS=`ls -1 ${USB_BLOCK_DEVICE}* | wc -l`-1 + if [ ${USB_NUM_PARTITIONS} -eq 0 ]; then + USB_MOUNT_DEVICE=${USB_BLOCK_DEVICE} + elif [ ${USB_NUM_PARTITIONS} -eq 1 ]; then + USB_MOUNT_DEVICE=`ls -1 ${USB_BLOCK_DEVICE}* | tail -n1` + fi +fi +# otherwise, let the user pick +if [ -z ${USB_MOUNT_DEVICE} ]; then + > /tmp/usb_disk_list + for i in `cat /tmp/usb_block_devices`; do + # remove block device from list if numeric partitions exist, since not bootable + let USB_NUM_PARTITIONS=`ls -1 $i* | wc -l`-1 if [ ${USB_NUM_PARTITIONS} -eq 0 ]; then - USB_MOUNT_DEVICE=${USB_BLOCK_DEVICE} - elif [ ${USB_NUM_PARTITIONS} -eq 1 ]; then - USB_MOUNT_DEVICE=`ls -1 ${USB_BLOCK_DEVICE}* | tail -n1` + echo $i >> /tmp/usb_disk_list + else + ls $i* | tail -${USB_NUM_PARTITIONS} >> /tmp/usb_disk_list fi - fi - # otherwise, let the user pick - if [ -z ${USB_MOUNT_DEVICE} ]; then - > /tmp/usb_disk_list - for i in `cat /tmp/usb_block_devices`; do - # remove block device from list if numeric partitions exist, since not bootable - let USB_NUM_PARTITIONS=`ls -1 $i* | wc -l`-1 - if [ ${USB_NUM_PARTITIONS} -eq 0 ]; then - echo $i >> /tmp/usb_disk_list - else - ls $i* | tail -${USB_NUM_PARTITIONS} >> /tmp/usb_disk_list - fi - done + done - if [ -x /bin/whiptail ]; then - MENU_OPTIONS="" - n=0 - while read option - do - n=`expr $n + 1` - option=$(echo $option | tr " " "_") - MENU_OPTIONS="$MENU_OPTIONS $n ${option}" - done < /tmp/usb_disk_list + if [ -x /bin/whiptail ]; then + MENU_OPTIONS="" + n=0 + while read option + do + n=`expr $n + 1` + option=$(echo $option | tr " " "_") + MENU_OPTIONS="$MENU_OPTIONS $n ${option}" + done < /tmp/usb_disk_list - MENU_OPTIONS="$MENU_OPTIONS a Abort" - whiptail --clear --title "Select your USB disk" \ - --menu "Choose your USB disk [1-$n, a to abort]:" 20 120 8 \ - -- $MENU_OPTIONS \ - 2>/tmp/whiptail + MENU_OPTIONS="$MENU_OPTIONS a Abort" + whiptail --clear --title "Select your USB disk" \ + --menu "Choose your USB disk [1-$n, a to abort]:" 20 120 8 \ + -- $MENU_OPTIONS \ + 2>/tmp/whiptail - option_index=$(cat /tmp/whiptail) - else - echo "+++ Select your USB disk:" - n=0 - while read option - do - n=`expr $n + 1` - echo "$n. $option" - done < /tmp/usb_disk_list - - read \ - -p "Choose your USB disk [1-$n, a to abort]: " \ - option_index - fi + option_index=$(cat /tmp/whiptail) + else + echo "+++ Select your USB disk:" + n=0 + while read option + do + n=`expr $n + 1` + echo "$n. $option" + done < /tmp/usb_disk_list - if [ "$option_index" = "a" ]; then - exit 1 - fi - USB_MOUNT_DEVICE=`head -n $option_index /tmp/usb_disk_list | tail -1` + read \ + -p "Choose your USB disk [1-$n, a to abort]: " \ + option_index fi - #Check if $USB_MOUNT_DEVICE is a LUKS encrypted device.Ff so, luksOpen it and replace $USB_MOUNT_DEVICE with /dev/mapper/usbdev - is_Luks_luksOpen - if [ "$1" = "rw" ]; then - mount -o rw $USB_MOUNT_DEVICE /media - else - mount -o ro $USB_MOUNT_DEVICE /media + if [ "$option_index" = "a" ]; then + exit 1 fi + USB_MOUNT_DEVICE=`head -n $option_index /tmp/usb_disk_list | tail -1` +fi + +#Check if $USB_MOUNT_DEVICE is a LUKS encrypted device.Ff so, luksOpen it and replace $USB_MOUNT_DEVICE with /dev/mapper/usbdev +is_Luks_luksOpen +if [ "$1" = "rw" ]; then + mount -o rw $USB_MOUNT_DEVICE /media +else + mount -o ro $USB_MOUNT_DEVICE /media fi From c1d26d8c947ac08c767e59b3c9f34c0c0b727ae6 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sat, 4 May 2019 16:36:55 -0400 Subject: [PATCH 36/91] initrd/bin/mount-usb: add error handling when mounting initrd/bin/factory-reset-nitrokey-libremkey.sh: use mount-usb according to kyle's change. --- initrd/bin/factory-reset-nitrokey-libremkey.sh | 14 +------------- initrd/bin/mount-usb | 4 ++-- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/initrd/bin/factory-reset-nitrokey-libremkey.sh b/initrd/bin/factory-reset-nitrokey-libremkey.sh index 6ba00f011..1f7cc8b48 100755 --- a/initrd/bin/factory-reset-nitrokey-libremkey.sh +++ b/initrd/bin/factory-reset-nitrokey-libremkey.sh @@ -7,19 +7,7 @@ set -e -o pipefail mount_usb(){ # Mount the USB boot device if ! grep -q /media /proc/mounts ; then - mount-usb "$CONFIG_USB_BOOT_DEV" || USB_FAILED=1 - if [ $USB_FAILED -ne 0 ]; then - if [ ! -e "$CONFIG_USB_BOOT_DEV" ]; then - whiptail --title 'USB Drive Missing' \ - --msgbox "Insert your USB drive and press Enter to continue." 16 60 USB_FAILED=0 - mount-usb "$CONFIG_USB_BOOT_DEV" || USB_FAILED=1 - fi - if [ $USB_FAILED -ne 0 ]; then - whiptail $CONFIG_ERROR_BG_COLOR --title 'ERROR: Mounting /media Failed' \ - --msgbox "Unable to mount $CONFIG_USB_BOOT_DEV" 16 60 - fi - fi - fi + mount-usb } if (whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'Factory Reset and reownership of GPG card' \ diff --git a/initrd/bin/mount-usb b/initrd/bin/mount-usb index 2c1849226..2bde4f00f 100755 --- a/initrd/bin/mount-usb +++ b/initrd/bin/mount-usb @@ -126,7 +126,7 @@ fi #Check if $USB_MOUNT_DEVICE is a LUKS encrypted device.Ff so, luksOpen it and replace $USB_MOUNT_DEVICE with /dev/mapper/usbdev is_Luks_luksOpen if [ "$1" = "rw" ]; then - mount -o rw $USB_MOUNT_DEVICE /media + mount -o rw $USB_MOUNT_DEVICE /media || die "Unable to remount /media into Read Write mode. Is the device write protected?" else - mount -o ro $USB_MOUNT_DEVICE /media + mount -o ro $USB_MOUNT_DEVICE /media || || die "Unable to mount $USB_MOUNT_DEVICE." fi From ff81d35cc7f76ffb038563cbca63acb80ecff5ed Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sat, 4 May 2019 22:27:46 -0400 Subject: [PATCH 37/91] initrd/bin/reencrypt-luks: homogenize whiptail messages. --- initrd/bin/reencrypt-luks | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/initrd/bin/reencrypt-luks b/initrd/bin/reencrypt-luks index 27869dbf6..f8edef512 100755 --- a/initrd/bin/reencrypt-luks +++ b/initrd/bin/reencrypt-luks @@ -55,8 +55,8 @@ if [ -n "$reownership_state" ] && [ "$reownership_state" = "luks_reencryption" ] #Validate past cryptsetup attempts if [ $(echo $?) -ne 0 ]; then - whiptail --title 'Invalid LUKS Disk Recovery Key passphrase?' --msgbox \ - "The LUKS Disk Recovery Key password 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.\n\nTo do so, place ISO file and its signature file on root of USB drive,\n and select Boot from USB\n\nHit Enter to continue." 30 60 + whiptail --title 'Invalid Actual LUKS Disk Recovery Key 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.\n\nTo do so, place ISO file and its signature file on root of USB drive,\n and select Boot from USB\n\nHit Enter to continue." 30 60 shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null #unsetting oem_luks_actual_Disk_Recovery_Key will prompt user for Disk Recovery Key passphrase prompt on next round unset oem_luks_actual_Disk_Recovery_Key From e6acde46314651845c14d2cb72fb25b3641fed59 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sat, 4 May 2019 22:30:42 -0400 Subject: [PATCH 38/91] Replace mount_usb calls by making mount-usb check if a device is mounted - affects initrd/bin/factory-reset-nitrokey-libremkey.sh initrd/bin/flash-gui.sh initrd/bin/gpg-gui.sh initrd/bin/mount-usb initrd/etc/functions - mount-usb now deals correctly with LUKS partitions. OEM are invited to provide users with an encrypted LUKS container encompassing a ext4 partition that contains oem-provisioning, ROM original images backups and flashed cleaned ME, with QubesOS certified rom image, and on second, unencrypted partition, the ISO images of his choice ( proposed: tails and latest QubesOS) Proper checks on /media/oem-provisioning: - Make sure that the format is respected: variable=test : test and following is kept, where 'variable=' is searched and discarded. - Warn on duplicates found, triggering error. - If error is found, recovery is lauched asking the user to review mounted /media for /media/oem-provisioning through vi (no, nano is not available in busybox, unfortunately. --- .../bin/factory-reset-nitrokey-libremkey.sh | 8 +- initrd/bin/flash-gui.sh | 20 +-- initrd/bin/gpg-gui.sh | 28 +-- initrd/bin/mount-usb | 160 +++++++++--------- initrd/etc/functions | 66 +++++--- 5 files changed, 134 insertions(+), 148 deletions(-) diff --git a/initrd/bin/factory-reset-nitrokey-libremkey.sh b/initrd/bin/factory-reset-nitrokey-libremkey.sh index 1f7cc8b48..4eb27972e 100755 --- a/initrd/bin/factory-reset-nitrokey-libremkey.sh +++ b/initrd/bin/factory-reset-nitrokey-libremkey.sh @@ -4,19 +4,13 @@ set -e -o pipefail . /etc/functions . /tmp/config -mount_usb(){ -# Mount the USB boot device - if ! grep -q /media /proc/mounts ; then - mount-usb -} - if (whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'Factory Reset and reownership of GPG card' \ --yesno "You are about to factory reset your GPG card!\n\nThis will:\n 1-Wipe all PRIVATE keys that were previously kept inside GPG card\n 2-Set default key size to 4096 bits (maximum)\n 3-Ask you to choose two passwords to interact with the card:\n 3.1: An administrative passphrase used to manage the card\n 3.2: A user passphrase (PIN) used everytime you sign\n encrypt/decrypt content\n4-Generate new Encryption, Signing and Authentication keys\n inside your GPG card\n5-Export associated public key, replace the one being\n present and trusted inside running BIOS, and reflash\n the SPI flash with resulting rom image.\n\nAs a result, the running BIOS will be modified. Would you like to continue?" 30 90) then whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'WARNING: Please Insert A USB Disk' --msgbox \ "Please insert a USB disk on which you want to store your GPG public key\n and trustdb.\n\nThose will be backuped under the 'gpg_keys' directory.\n\nHit Enter to continue." 30 90 - mount_usb || die "Unable to mount USB device." + mount-usb || die "Unable to mount USB device." #Copy generated public key, private_subkey, trustdb and artifacts to external media for backup: mount -o remount,rw /media || die "Unable to remount /media into Read Write mode. Is the device write protected?" diff --git a/initrd/bin/flash-gui.sh b/initrd/bin/flash-gui.sh index 6828b9ceb..4e5fcbb78 100755 --- a/initrd/bin/flash-gui.sh +++ b/initrd/bin/flash-gui.sh @@ -4,24 +4,6 @@ set -e -o pipefail . /etc/functions . /tmp/config -mount_usb(){ -# Mount the USB boot device - if ! grep -q /media /proc/mounts ; then - mount-usb "$CONFIG_USB_BOOT_DEV" || USB_FAILED=1 - if [ $USB_FAILED -ne 0 ]; then - if [ ! -e "$CONFIG_USB_BOOT_DEV" ]; then - whiptail --title 'USB Drive Missing' \ - --msgbox "Insert your USB drive and press Enter to continue." 16 60 USB_FAILED=0 - mount-usb "$CONFIG_USB_BOOT_DEV" || USB_FAILED=1 - fi - if [ $USB_FAILED -ne 0 ]; then - whiptail $CONFIG_ERROR_BG_COLOR --title 'ERROR: Mounting /media Failed' \ - --msgbox "Unable to mount $CONFIG_USB_BOOT_DEV" 16 60 - fi - fi - fi -} - while true; do unset menu_choice whiptail --clear --title "Firmware Management Menu" \ @@ -40,7 +22,7 @@ while true; do f|c ) if (whiptail --title 'Flash the BIOS with a new ROM' \ --yesno "This requires you insert a USB drive containing:\n* Your BIOS image (*.rom)\n\nAfter you select this file, this program will reflash your BIOS\n\nDo you want to proceed?" 16 90) then - mount_usb + mount-usb || die "Unable to mount USB device." if grep -q /media /proc/mounts ; then find /media -name '*.rom' > /tmp/filelist.txt file_selector "/tmp/filelist.txt" "Choose the ROM to flash" diff --git a/initrd/bin/gpg-gui.sh b/initrd/bin/gpg-gui.sh index 50438d57f..6ffe67885 100755 --- a/initrd/bin/gpg-gui.sh +++ b/initrd/bin/gpg-gui.sh @@ -4,24 +4,6 @@ set -e -o pipefail . /etc/functions . /tmp/config -mount_usb(){ -# Mount the USB boot device - if ! grep -q /media /proc/mounts ; then - mount-usb "$CONFIG_USB_BOOT_DEV" || USB_FAILED=1 - if [ $USB_FAILED -ne 0 ]; then - if [ ! -e "$CONFIG_USB_BOOT_DEV" ]; then - whiptail --title 'USB Drive Missing' \ - --msgbox "Insert your USB drive and press Enter to continue." 16 60 USB_FAILED=0 - mount-usb "$CONFIG_USB_BOOT_DEV" || USB_FAILED=1 - fi - if [ $USB_FAILED -ne 0 ]; then - whiptail $CONFIG_ERROR_BG_COLOR --title 'ERROR: Mounting /media Failed' \ - --msgbox "Unable to mount $CONFIG_USB_BOOT_DEV" 16 60 - fi - fi - fi -} - gpg_flash_rom() { cat "$PUBKEY" | gpg --import #update /.gnupg/trustdb.gpg to ultimately trust all user provided public keys @@ -69,8 +51,8 @@ gpg_post_gen_mgmt() { gpg --export --armor $GPG_GEN_KEY > "/tmp/${GPG_GEN_KEY}.asc" if (whiptail --title 'Add Public Key to USB disk?' \ --yesno "Would you like to copy the GPG public key you generated to a USB disk?\n\nOtherwise you will not be able to copy it outside of Heads later\n\nThe file will show up as ${GPG_GEN_KEY}.asc" 16 90) then - mount_usb - mount -o remount,rw /media + mount-usb || die "Unable to mount USB device." + mount -o remount,rw /media || die "Unable to remount /media in Read-Write mode. Is the device Write protected?" cp "/tmp/${GPG_GEN_KEY}.asc" "/media/${GPG_GEN_KEY}.asc" if [ $? -eq 0 ]; then whiptail --title "The GPG Key Copied Successfully" \ @@ -139,7 +121,7 @@ while true; do "a" ) if (whiptail --title 'ROM and GPG public key required' \ --yesno "This requires you insert a USB drive containing:\n* Your GPG public key (*.key or *.asc)\n* Your BIOS image (*.rom)\n\nAfter you select these files, this program will reflash your BIOS\n\nDo you want to proceed?" 16 90) then - mount_usb + mount-usb || die "Unable to mount USB device." if grep -q /media /proc/mounts ; then find /media -name '*.key' > /tmp/filelist.txt find /media -name '*.asc' >> /tmp/filelist.txt @@ -171,7 +153,7 @@ while true; do "r" ) if (whiptail --title 'GPG public key required' \ --yesno "This requires you insert a USB drive containing:\n* Your GPG public key (*.key or *.asc)\n\nAfter you select this file, this program will copy and reflash your BIOS\n\nDo you want to proceed?" 16 90) then - mount_usb + mount-usb || die "Unable to mount USB device." if grep -q /media /proc/mounts ; then find /media -name '*.key' > /tmp/filelist.txt find /media -name '*.asc' >> /tmp/filelist.txt @@ -238,4 +220,4 @@ while true; do esac done -exit 0 \ No newline at end of file +exit 0 diff --git a/initrd/bin/mount-usb b/initrd/bin/mount-usb index 2bde4f00f..2e0811e30 100755 --- a/initrd/bin/mount-usb +++ b/initrd/bin/mount-usb @@ -35,98 +35,104 @@ if [ ! -d /media ]; then mkdir /media fi -stat -c %N /sys/block/sd* | grep usb | cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" > /tmp/usb_block_devices -#In case CONFIG_USB_BOOT_DEV was just a secondary device specified in board configuration and found, add it to the list -stat -c %N $CONFIG_USB_BOOT_DEV | grep -v usb| cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" >> /tmp/usb_block_devices -if [ -z `cat /tmp/usb_block_devices` ]; then - if [ -x /bin/whiptail ]; then - whiptail --title 'USB Drive Missing' \ - --msgbox "Insert your USB drive and press Enter to continue." 16 60 - else - echo "+++ USB Drive Missing! Insert your USB drive and press Enter to continue." - read - fi - sleep 1 +if ! grep -q /media /proc/mounts ; then stat -c %N /sys/block/sd* | grep usb | cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" > /tmp/usb_block_devices #In case CONFIG_USB_BOOT_DEV was just a secondary device specified in board configuration and found, add it to the list - stat -c %N $CONFIG_USB_BOOT_DEV | grep -v usb| cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" >> /tmp/usb_block_devices + stat -c %N $CONFIG_USB_BOOT_DEV | grep -v usb| cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" >> /tmp/usb_block_devices + devices=$(cat /tmp/usb_block_devices |uniq|sort) + echo "$devices" > /tmp/usb_block_devices if [ -z `cat /tmp/usb_block_devices` ]; then if [ -x /bin/whiptail ]; then - whiptail $CONFIG_ERROR_BG_COLOR --title 'ERROR: USB Drive Missing' \ - --msgbox "USB Drive Missing! Aborting mount attempt.\n\nPress Enter to continue." 16 60 + whiptail --title 'USB Drive Missing' \ + --msgbox "Insert your USB drive and press Enter to continue." 16 60 else - echo "!!! ERROR: USB Drive Missing! Aborting mount. Press Enter to continue." + echo "+++ USB Drive Missing! Insert your USB drive and press Enter to continue." + read + fi + sleep 1 + stat -c %N /sys/block/sd* | grep usb | cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" > /tmp/usb_block_devices + #In case CONFIG_USB_BOOT_DEV was just a secondary device specified in board configuration and found, add it to the list + stat -c %N $CONFIG_USB_BOOT_DEV | grep -v usb| cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" >> /tmp/usb_block_devices + devices=$(cat /tmp/usb_block_devices |uniq|sort) + echo "$devices" > /tmp/usb_block_devices + if [ -z `cat /tmp/usb_block_devices` ]; then + if [ -x /bin/whiptail ]; then + whiptail $CONFIG_ERROR_BG_COLOR --title 'ERROR: USB Drive Missing' \ + --msgbox "USB Drive Missing! Aborting mount attempt.\n\nPress Enter to continue." 16 60 + else + echo "!!! ERROR: USB Drive Missing! Aborting mount. Press Enter to continue." + fi + exit 1 fi - exit 1 fi -fi -USB_MOUNT_DEVICE="" -# Check for the common case: a single USB disk with one partition -if [ `cat /tmp/usb_block_devices | wc -l` -eq 1 ]; then - USB_BLOCK_DEVICE=`cat /tmp/usb_block_devices` - # Subtract out block device - let USB_NUM_PARTITIONS=`ls -1 ${USB_BLOCK_DEVICE}* | wc -l`-1 - if [ ${USB_NUM_PARTITIONS} -eq 0 ]; then - USB_MOUNT_DEVICE=${USB_BLOCK_DEVICE} - elif [ ${USB_NUM_PARTITIONS} -eq 1 ]; then - USB_MOUNT_DEVICE=`ls -1 ${USB_BLOCK_DEVICE}* | tail -n1` - fi -fi -# otherwise, let the user pick -if [ -z ${USB_MOUNT_DEVICE} ]; then - > /tmp/usb_disk_list - for i in `cat /tmp/usb_block_devices`; do - # remove block device from list if numeric partitions exist, since not bootable - let USB_NUM_PARTITIONS=`ls -1 $i* | wc -l`-1 + USB_MOUNT_DEVICE="" + # Check for the common case: a single USB disk with one partition + if [ `cat /tmp/usb_block_devices | wc -l` -eq 1 ]; then + USB_BLOCK_DEVICE=`cat /tmp/usb_block_devices` + # Subtract out block device + let USB_NUM_PARTITIONS=`ls -1 ${USB_BLOCK_DEVICE}* | wc -l`-1 if [ ${USB_NUM_PARTITIONS} -eq 0 ]; then - echo $i >> /tmp/usb_disk_list - else - ls $i* | tail -${USB_NUM_PARTITIONS} >> /tmp/usb_disk_list + USB_MOUNT_DEVICE=${USB_BLOCK_DEVICE} + elif [ ${USB_NUM_PARTITIONS} -eq 1 ]; then + USB_MOUNT_DEVICE=`ls -1 ${USB_BLOCK_DEVICE}* | tail -n1` fi - done + fi + # otherwise, let the user pick + if [ -z ${USB_MOUNT_DEVICE} ]; then + > /tmp/usb_disk_list + for i in `cat /tmp/usb_block_devices`; do + # remove block device from list if numeric partitions exist, since not bootable + let USB_NUM_PARTITIONS=`ls -1 $i* | wc -l`-1 + if [ ${USB_NUM_PARTITIONS} -eq 0 ]; then + echo $i >> /tmp/usb_disk_list + else + ls $i* | tail -${USB_NUM_PARTITIONS} >> /tmp/usb_disk_list + fi + done - if [ -x /bin/whiptail ]; then - MENU_OPTIONS="" - n=0 - while read option - do - n=`expr $n + 1` - option=$(echo $option | tr " " "_") - MENU_OPTIONS="$MENU_OPTIONS $n ${option}" - done < /tmp/usb_disk_list + if [ -x /bin/whiptail ]; then + MENU_OPTIONS="" + n=0 + while read option + do + n=`expr $n + 1` + option=$(echo $option | tr " " "_") + MENU_OPTIONS="$MENU_OPTIONS $n ${option}" + done < /tmp/usb_disk_list - MENU_OPTIONS="$MENU_OPTIONS a Abort" - whiptail --clear --title "Select your USB disk" \ - --menu "Choose your USB disk [1-$n, a to abort]:" 20 120 8 \ - -- $MENU_OPTIONS \ - 2>/tmp/whiptail + MENU_OPTIONS="$MENU_OPTIONS a Abort" + whiptail --clear --title "Select your USB disk" \ + --menu "Choose your USB disk [1-$n, a to abort]:" 20 120 8 \ + -- $MENU_OPTIONS \ + 2>/tmp/whiptail - option_index=$(cat /tmp/whiptail) - else - echo "+++ Select your USB disk:" - n=0 - while read option - do - n=`expr $n + 1` - echo "$n. $option" - done < /tmp/usb_disk_list + option_index=$(cat /tmp/whiptail) + else + echo "+++ Select your USB disk:" + n=0 + while read option + do + n=`expr $n + 1` + echo "$n. $option" + done < /tmp/usb_disk_list - read \ - -p "Choose your USB disk [1-$n, a to abort]: " \ - option_index - fi + read \ + -p "Choose your USB disk [1-$n, a to abort]: " \ + option_index + fi - if [ "$option_index" = "a" ]; then - exit 1 + if [ "$option_index" = "a" ]; then + exit 1 + fi + USB_MOUNT_DEVICE=`head -n $option_index /tmp/usb_disk_list | tail -1` fi - USB_MOUNT_DEVICE=`head -n $option_index /tmp/usb_disk_list | tail -1` -fi -#Check if $USB_MOUNT_DEVICE is a LUKS encrypted device.Ff so, luksOpen it and replace $USB_MOUNT_DEVICE with /dev/mapper/usbdev -is_Luks_luksOpen -if [ "$1" = "rw" ]; then - mount -o rw $USB_MOUNT_DEVICE /media || die "Unable to remount /media into Read Write mode. Is the device write protected?" -else - mount -o ro $USB_MOUNT_DEVICE /media || || die "Unable to mount $USB_MOUNT_DEVICE." + #Check if $USB_MOUNT_DEVICE is a LUKS encrypted device.Ff so, luksOpen it and replace $USB_MOUNT_DEVICE with /dev/mapper/usbdev + is_Luks_luksOpen + if [ "$1" = "rw" ]; then + mount -o rw $USB_MOUNT_DEVICE /media + else + mount -o ro $USB_MOUNT_DEVICE /media + fi fi diff --git a/initrd/etc/functions b/initrd/etc/functions index 9dee82a4a..c66e75c4d 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -314,71 +314,93 @@ combine_configs() { read_oem_file() { echo "Mounting USB drive to provision OEM reownership from /media/oem-provisioning..." - /bin/mount-usb || warn "Unable to mount USB device. Continuing" + /bin/mount-usb rw || warn "Unable to mount USB device. Continuing" if [ -e /media/oem-provisioning ]; then - oem_gpg_Admin_PIN=$(grep "oem_gpg_Admin_PIN" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_gpg_Admin_PIN" ]; then + oem_gpg_Admin_PIN=$(grep "oem_gpg_Admin_PIN=" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_gpg_Admin_PIN" ] && [ $(echo "$oem_gpg_Admin_PIN" | wc -l ) -eq 1 ]; then export oem_gpg_Admin_PIN="$oem_gpg_Admin_PIN" else + warn "Multiple 'oem_gpg_Admin_PIN=' statements found. None retained." unset oem_gpg_Admin_PIN + error=1 fi - oem_gpg_User_PIN=$(grep "oem_gpg_User_PIN" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_gpg_User_PIN" ]; then + oem_gpg_User_PIN=$(grep "oem_gpg_User_PIN=" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_gpg_User_PIN" ] && [ $(echo "$oem_gpg_User_PIN" | wc -l ) -eq 1 ]; then export oem_gpg_User_PIN="$oem_gpg_User_PIN" else - unset oem_gpg_User_PIN + warn "Multiple 'oem_gpg_User_PIN=' statements found. None retained." + unset oem_gpg_User_PIN + error=1 fi - oem_gpg_real_name=$(grep "oem_gpg_real_name" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_gpg_real_name" ]; then + oem_gpg_real_name=$(grep "oem_gpg_real_name=" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_gpg_real_name" ] && [ $(echo "$oem_gpg_real_name" | wc -l ) -eq 1 ]; then export oem_gpg_real_name="$oem_gpg_real_name" else + warn "Multiple 'oem_gpg_real_name=' statements found. None retained." unset oem_gpg_real_name + error=1 fi - oem_gpg_email=$(grep "oem_gpg_email" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_gpg_email" ]; then + oem_gpg_email=$(grep "oem_gpg_email=" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_gpg_email" ] && [ $(echo "$oem_gpg_email" | wc -l ) -eq 1 ]; then export oem_gpg_email="$oem_gpg_email" else - unset oem_gpg_email + warn "Multiple 'oem_gpg_email=' statements found. None retained." + unset oem_gpg_email + error=1 fi - oem_gpg_comment=$(grep "oem_gpg_comment" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_gpg_comment" ]; then + oem_gpg_comment=$(grep "oem_gpg_comment=" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_gpg_comment" ] && [ $(echo "$oem_gpg_comment" | wc -l ) -eq 1 ]; then export oem_gpg_comment="$oem_gpg_comment" else + warn "Multiple 'oem_gpg_comment=' statements found. None retained." unset oem_gpg_comment + error=1 fi - oem_luks_actual_Disk_Recovery_Key=$(grep "oem_luks_actual_Disk_Recovery_Key" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_luks_actual_Disk_Recovery_Key" ]; then + oem_luks_actual_Disk_Recovery_Key=$(grep "oem_luks_actual_Disk_Recovery_Key=" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_luks_actual_Disk_Recovery_Key" ] && [ $(echo "$oem_luks_actual_Disk_Recovery_Key" | wc -l ) -eq 1 ]; then export oem_luks_actual_Disk_Recovery_Key="$oem_luks_actual_Disk_Recovery_Key" else + warn "Multiple 'oem_luks_actual_Disk_Recovery_Key=' statements found. None retained." unset oem_luks_actual_Disk_Recovery_Key + error=1 fi - oem_luks_new_Disk_Recovery_Key=$(grep "oem_luks_new_Disk_Recovery_Key" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_luks_new_Disk_Recovery_Key" ]; then + oem_luks_new_Disk_Recovery_Key=$(grep "oem_luks_new_Disk_Recovery_Key=" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_luks_new_Disk_Recovery_Key" ] && [ $(echo "$oem_luks_new_Disk_Recovery_Key" | wc -l ) -eq 1 ]; then export oem_luks_new_Disk_Recovery_Key="$oem_luks_new_Disk_Recovery_Key" else + warn "Multiple 'oem_luks_new_Disk_Recovery_Key=' statements found. None retained." unset oem_luks_new_Disk_Recovery_Key + error=1 fi - oem_luks_Disk_Unlock_Key=$(grep "oem_luks_Disk_Unlock_Key" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_luks_Disk_Unlock_Key" ]; then + oem_luks_Disk_Unlock_Key=$(grep "oem_luks_Disk_Unlock_Key=" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_luks_Disk_Unlock_Key" ] && [ $(echo "$oem_luks_Disk_Unlock_Key" | wc -l ) -eq 1 ]; then export oem_luks_Disk_Unlock_Key="$oem_luks_Disk_Unlock_Key" else + warn "Multiple 'oem_luks_Disk_Unlock_Key=' statements found. None retained." unset oem_luks_Disk_Unlock_Key + error=1 fi - oem_TPM_Owner_Password=$(grep "oem_TPM_Owner_Password" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_TPM_Owner_Password" ]; then + oem_TPM_Owner_Password=$(grep "oem_TPM_Owner_Password=" /media/oem-provisioning | cut -d "=" -f2) + if [ -n "$oem_TPM_Owner_Password" ] && [ $(echo "$oem_TPM_Owner_Password" | wc -l ) -eq 1 ]; then export oem_TPM_Owner_Password="$oem_TPM_Owner_Password" else + warn "Multiple 'oem_TPM_Owner_Password=' statements found. None retained." unset oem_TPM_Owner_Password + error=1 fi - + + if [ -n $error ] && [ "$error" -eq 1 ]; then + recovery "Please run 'vi /media/oem-provisioning' to correct previous warnings. ('i': insert, modify, 'Esc' key, then ':wq', 'Enter', then 'unmount /media' and 'reboot'." + fi + export oem_configuration_read=1 umount /media fi From b7ddcdbd8c800d934db3321a1ca37d7b24d976b3 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sun, 5 May 2019 02:13:29 -0400 Subject: [PATCH 39/91] initrd/.ash_history: Take into consideration current state of other commands to be one-liners to be easily modified from history --- initrd/.ash_history | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/initrd/.ash_history b/initrd/.ash_history index 5c292979e..e6f5303e0 100644 --- a/initrd/.ash_history +++ b/initrd/.ash_history @@ -1,22 +1,21 @@ #To activate OEM reownership wizard, under Heads recovery console, do: -mount /boot -mount -o remount,rw /boot && echo "oem_name=COMPANY NAME" > /boot/oem && mount -o remount,ro /boot && reboot +mount /boot||true && mount -o remount,rw /boot && echo "oem_name=COMPANY NAME" > /boot/oem && mount -o remount,ro /boot && reboot #remove invalid kexec.sig signed checksum file -mount /dev/sda1 /boot && mount -o remount,rw /boot && rm /boot/kexec.sig && mount -o remount,ro /boot +mount /boot||true && mount -o remount,rw /boot && rm /boot/kexec.sig && mount -o remount,ro /boot #Generate keys from GPG smartcard: usb-init && gpg --home=/.gnupg/ --card-edit #Copy generated public key, private_subkey, trustdb and artifacts to external media for backup: -mount -o remount,rw /media && mkdir -p /media/gpg_keys; gpg --export-secret-keys --armor email@address.com > /media/gpg_keys/private.key && gpg --export --armor email@address.com > /media/gpg_keys/public.key && cp -r ./.gnupg/* /media/gpg_keys/ 2> /dev/null +mount-usb && mount -o remount,rw /media && mkdir -p /media/gpg_keys; gpg --export-secret-keys --armor email@address.com > /media/gpg_keys/private.key && gpg --export --armor email@address.com > /media/gpg_keys/public.key && cp -r ./.gnupg/* /media/gpg_keys/ 2> /dev/null #Insert public key and trustdb export into reproducible rom: cbfs -o /media/coreboot.rom -a "heads/initrd/.gnupg/keys/public.key" -f /media/gpg_keys/public.key #Flush changes to external media: mount -o,remount ro /media #Flash modified reproducible rom with inserted public key and trustdb export from precedent step. Flushes actual rom's keys (-c: clean): -flash.sh -c /media/coreboot.rom +mount-usb && flash.sh -c /media/coreboot.rom #Attest integrity of firmware as it is seal-totp #Sign a manually verified ISO with your GPG key so you can boot it from Heads -mount-usb && gpg --card-status && gpg --detach-sig /media/some.iso +mount-usb && mount -o remount,rw /media && gpg --card-status && gpg --detach-sig /media/some.iso #Verify Intel ME state: cbmem --console | grep '^ME' cbmem --console | less From 17273a7af08d923586b9339913750cf9bb6e8880 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Tue, 7 May 2019 21:21:28 -0400 Subject: [PATCH 40/91] Uniformize and limit unrequired changes to master. --- initrd/bin/flash-gui.sh | 2 +- initrd/bin/gui-init | 8 +------- initrd/bin/mount-usb | 1 + initrd/bin/tpm-reset | 4 ++-- initrd/etc/functions | 14 ++++++++------ modules/pixman | 2 +- 6 files changed, 14 insertions(+), 17 deletions(-) diff --git a/initrd/bin/flash-gui.sh b/initrd/bin/flash-gui.sh index 4e5fcbb78..6352ba1ce 100755 --- a/initrd/bin/flash-gui.sh +++ b/initrd/bin/flash-gui.sh @@ -40,7 +40,7 @@ while true; do /bin/flash.sh "$ROM" fi whiptail --title 'ROM Flashed Successfully' \ - --msgbox "$ROM flashed successfully.\nPress Enter to reboot" 16 60 + --msgbox "$ROM flashed successfully.\nPress Enter to reboot" 16 60 umount /media /bin/reboot else diff --git a/initrd/bin/gui-init b/initrd/bin/gui-init index 08fb1a618..4ec184de7 100755 --- a/initrd/bin/gui-init +++ b/initrd/bin/gui-init @@ -118,10 +118,6 @@ if [ -e /boot/oem ];then fi fi - -#TODO:validate that resetting disk unlock key only happens when /boot/oem doesn't exist anymore. Should happen after TPM reset. -#Flashing modifies measurements, which should trigger TOTP/HOTP resealing. That happens when inserting gpg public key. -#Measurements become invalid when TPM is reset, also. if [ -e /boot/reset_disk_unlock_key ] && [ ! -e /boot/oem ]; then if (whiptail $CONFIG_WARNING_BG_COLOR --title "WARNING: You must change your Disk Unlock Key" \ --yesno "You just updated the ROM, which requires resealing TOTP/HOTP secrets.\nTPM released Disk Unlock Key stored in LUKS header must also be regenerated.\n\nIf you did not modify the ROM, this might be a sign of system compromise.\nIn that case, you should say No here and investigate." 30 90) then @@ -148,7 +144,6 @@ while true; do totp_confirm=$(cat /tmp/whiptail) fi - if [ "$totp_confirm" = "i" -o -z "$totp_confirm" ]; then # update the TOTP code every thirty seconds date=`date "+%Y-%m-%d %H:%M:%S"` @@ -160,14 +155,13 @@ while true; do last_half=$half; TOTP=`unseal-totp` if [ $? -ne 0 ]; then - #Normal path. We give user a choice. whiptail $CONFIG_ERROR_BG_COLOR --clear --title "ERROR: TOTP Generation Failed!" \ --menu "ERROR: Heads couldn't generate the TOTP code.\n\nIf this is the first time the system has booted, you should reset the TPM\nand set your own password\n\nIf you just reflashed your BIOS, you'll need to generate a new TOTP secret.\n\nIf you have not just reflashed your BIOS, THIS COULD INDICATE TAMPERING!\n\nHow would you like to proceed?" 30 90 4 \ 'g' ' Generate new TOTP/HOTP secret' \ 'i' ' Ignore error and continue to default boot menu' \ 'p' ' Reset the TPM' \ 'x' ' Exit to recovery shell' \ - 2>/tmp/whiptail || recovery "GUI menu failed" + 2>/tmp/whiptail || recovery "GUI menu failed" totp_confirm=$(cat /tmp/whiptail) fi diff --git a/initrd/bin/mount-usb b/initrd/bin/mount-usb index 2e0811e30..6c26bccf0 100755 --- a/initrd/bin/mount-usb +++ b/initrd/bin/mount-usb @@ -35,6 +35,7 @@ if [ ! -d /media ]; then mkdir /media fi +#Only mount /media device if not mounted. Calling scripts are responsible to unmount when done if another script might need a different USB drive. if ! grep -q /media /proc/mounts ; then stat -c %N /sys/block/sd* | grep usb | cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" > /tmp/usb_block_devices #In case CONFIG_USB_BOOT_DEV was just a secondary device specified in board configuration and found, add it to the list diff --git a/initrd/bin/tpm-reset b/initrd/bin/tpm-reset index 7a929ba68..74c7bf0bf 100755 --- a/initrd/bin/tpm-reset +++ b/initrd/bin/tpm-reset @@ -37,9 +37,9 @@ tpm physicalenable tpm physicalsetdeactivated -c tpm forceclear tpm physicalenable -tpm takeown -pwdo "$key_password" >/dev/null 2>&1 +tpm takeown -pwdo "$key_password" >/dev/null 2>&1 # And now turn it all back on tpm physicalpresence -s -tpm physicalenable >/dev/null +tpm physicalenable tpm physicalsetdeactivated -c diff --git a/initrd/etc/functions b/initrd/etc/functions index c66e75c4d..c5a85d17e 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -347,7 +347,7 @@ read_oem_file() if [ -n "$oem_gpg_email" ] && [ $(echo "$oem_gpg_email" | wc -l ) -eq 1 ]; then export oem_gpg_email="$oem_gpg_email" else - warn "Multiple 'oem_gpg_email=' statements found. None retained." + warn "Multiple 'oem_gpg_email=' statements found. None retained." unset oem_gpg_email error=1 fi @@ -398,13 +398,14 @@ read_oem_file() fi if [ -n $error ] && [ "$error" -eq 1 ]; then - recovery "Please run 'vi /media/oem-provisioning' to correct previous warnings. ('i': insert, modify, 'Esc' key, then ':wq', 'Enter', then 'unmount /media' and 'reboot'." + recovery "Please run 'vi /media/oem-provisioning' to correct previous warnings. ('i': insert, modify, 'Esc' key, then ':wq', 'Enter' key, then 'unmount /media' and 'reboot'." fi export oem_configuration_read=1 umount /media fi } + check_onboarding_progress() { mount_boot @@ -422,25 +423,25 @@ check_onboarding_progress() echo "onboarding" >> /boot/oem mount -o remount,ro /boot fi - res=$(grep luks_reencrypted /boot/oem 2>&1 > /dev/null) + res=$(grep luks_reencrypted /boot/oem > /dev/null 2>&1) if [ $? -ne 0 ];then export reownership_state="luks_reencryption" totp_confirm="R" echo $totp_confirm > /tmp/whiptail return fi - res=$(grep luks_passwd_changed /boot/oem 2>&1 > /dev/null) + res=$(grep luks_passwd_changed /boot/oem > /dev/null 2>&1) if [ $? -ne 0 ];then export reownership_state="luks_password_change" totp_confirm="R" return fi - res=$(grep gpg_factory_resetted /boot/oem 2>&1 > /dev/null) + res=$(grep gpg_factory_resetted /boot/oem > /dev/null 2>&1) if [ $? -ne 0 ];then /bin/factory-reset-nitrokey-libremkey.sh return fi - res=$(grep tpm_reowned /boot/oem 2>&1 > /dev/null) + res=$(grep tpm_reowned /boot/oem > /dev/null 2>&1) if [ $? -ne 0 ];then totp_confirm="p" echo $totp_confirm > /tmp/whiptail @@ -476,6 +477,7 @@ check_onboarding_progress() return fi } + reset_disk_unlock_key() { mount_boot diff --git a/modules/pixman b/modules/pixman index 8bd54a900..137a5ea18 100644 --- a/modules/pixman +++ b/modules/pixman @@ -9,7 +9,7 @@ pixman_hash := 21b6b249b51c6800dc9553b65106e1e37d0e25df942c90531d4c3997aa20a88e pixman_configure := \ $(CROSS_TOOLS) \ ./configure \ - --host i386-elf-linux \ + --host i386-elf-linux \ --prefix="/" \ --disable-gtk From d50cfa4a706e4b304a17a3f864e1ca620421515f Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Thu, 9 May 2019 09:44:00 -0400 Subject: [PATCH 41/91] initrd/etc/functions: reading of /media/oem-provisioning takes into consideration only variables starting lines. --- initrd/etc/functions | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/initrd/etc/functions b/initrd/etc/functions index c5a85d17e..cccad285a 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -316,7 +316,7 @@ read_oem_file() echo "Mounting USB drive to provision OEM reownership from /media/oem-provisioning..." /bin/mount-usb rw || warn "Unable to mount USB device. Continuing" if [ -e /media/oem-provisioning ]; then - oem_gpg_Admin_PIN=$(grep "oem_gpg_Admin_PIN=" /media/oem-provisioning | cut -d "=" -f2) + oem_gpg_Admin_PIN=$(grep "^oem_gpg_Admin_PIN=" /media/oem-provisioning | cut -d "=" -f2) if [ -n "$oem_gpg_Admin_PIN" ] && [ $(echo "$oem_gpg_Admin_PIN" | wc -l ) -eq 1 ]; then export oem_gpg_Admin_PIN="$oem_gpg_Admin_PIN" else @@ -325,7 +325,7 @@ read_oem_file() error=1 fi - oem_gpg_User_PIN=$(grep "oem_gpg_User_PIN=" /media/oem-provisioning | cut -d "=" -f2) + oem_gpg_User_PIN=$(grep "^oem_gpg_User_PIN=" /media/oem-provisioning | cut -d "=" -f2) if [ -n "$oem_gpg_User_PIN" ] && [ $(echo "$oem_gpg_User_PIN" | wc -l ) -eq 1 ]; then export oem_gpg_User_PIN="$oem_gpg_User_PIN" else @@ -334,7 +334,7 @@ read_oem_file() error=1 fi - oem_gpg_real_name=$(grep "oem_gpg_real_name=" /media/oem-provisioning | cut -d "=" -f2) + oem_gpg_real_name=$(grep "^oem_gpg_real_name=" /media/oem-provisioning | cut -d "=" -f2) if [ -n "$oem_gpg_real_name" ] && [ $(echo "$oem_gpg_real_name" | wc -l ) -eq 1 ]; then export oem_gpg_real_name="$oem_gpg_real_name" else @@ -343,7 +343,7 @@ read_oem_file() error=1 fi - oem_gpg_email=$(grep "oem_gpg_email=" /media/oem-provisioning | cut -d "=" -f2) + oem_gpg_email=$(grep "^oem_gpg_email=" /media/oem-provisioning | cut -d "=" -f2) if [ -n "$oem_gpg_email" ] && [ $(echo "$oem_gpg_email" | wc -l ) -eq 1 ]; then export oem_gpg_email="$oem_gpg_email" else @@ -352,7 +352,7 @@ read_oem_file() error=1 fi - oem_gpg_comment=$(grep "oem_gpg_comment=" /media/oem-provisioning | cut -d "=" -f2) + oem_gpg_comment=$(grep "^oem_gpg_comment=" /media/oem-provisioning | cut -d "=" -f2) if [ -n "$oem_gpg_comment" ] && [ $(echo "$oem_gpg_comment" | wc -l ) -eq 1 ]; then export oem_gpg_comment="$oem_gpg_comment" else @@ -361,7 +361,7 @@ read_oem_file() error=1 fi - oem_luks_actual_Disk_Recovery_Key=$(grep "oem_luks_actual_Disk_Recovery_Key=" /media/oem-provisioning | cut -d "=" -f2) + oem_luks_actual_Disk_Recovery_Key=$(grep "^oem_luks_actual_Disk_Recovery_Key=" /media/oem-provisioning | cut -d "=" -f2) if [ -n "$oem_luks_actual_Disk_Recovery_Key" ] && [ $(echo "$oem_luks_actual_Disk_Recovery_Key" | wc -l ) -eq 1 ]; then export oem_luks_actual_Disk_Recovery_Key="$oem_luks_actual_Disk_Recovery_Key" else @@ -370,7 +370,7 @@ read_oem_file() error=1 fi - oem_luks_new_Disk_Recovery_Key=$(grep "oem_luks_new_Disk_Recovery_Key=" /media/oem-provisioning | cut -d "=" -f2) + oem_luks_new_Disk_Recovery_Key=$(grep "^oem_luks_new_Disk_Recovery_Key=" /media/oem-provisioning | cut -d "=" -f2) if [ -n "$oem_luks_new_Disk_Recovery_Key" ] && [ $(echo "$oem_luks_new_Disk_Recovery_Key" | wc -l ) -eq 1 ]; then export oem_luks_new_Disk_Recovery_Key="$oem_luks_new_Disk_Recovery_Key" else @@ -379,7 +379,7 @@ read_oem_file() error=1 fi - oem_luks_Disk_Unlock_Key=$(grep "oem_luks_Disk_Unlock_Key=" /media/oem-provisioning | cut -d "=" -f2) + oem_luks_Disk_Unlock_Key=$(grep "^oem_luks_Disk_Unlock_Key=" /media/oem-provisioning | cut -d "=" -f2) if [ -n "$oem_luks_Disk_Unlock_Key" ] && [ $(echo "$oem_luks_Disk_Unlock_Key" | wc -l ) -eq 1 ]; then export oem_luks_Disk_Unlock_Key="$oem_luks_Disk_Unlock_Key" else @@ -388,7 +388,7 @@ read_oem_file() error=1 fi - oem_TPM_Owner_Password=$(grep "oem_TPM_Owner_Password=" /media/oem-provisioning | cut -d "=" -f2) + oem_TPM_Owner_Password=$(grep "^oem_TPM_Owner_Password=" /media/oem-provisioning | cut -d "=" -f2) if [ -n "$oem_TPM_Owner_Password" ] && [ $(echo "$oem_TPM_Owner_Password" | wc -l ) -eq 1 ]; then export oem_TPM_Owner_Password="$oem_TPM_Owner_Password" else From ac1f518efee5a0afad69f876ba38f01c6e9d769c Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sun, 12 May 2019 19:46:31 -0400 Subject: [PATCH 42/91] initrd/bin/mount-usb: revert changes implying non-usb block devices --- initrd/bin/mount-usb | 8 -------- 1 file changed, 8 deletions(-) diff --git a/initrd/bin/mount-usb b/initrd/bin/mount-usb index 6c26bccf0..b059fdc36 100755 --- a/initrd/bin/mount-usb +++ b/initrd/bin/mount-usb @@ -38,10 +38,6 @@ fi #Only mount /media device if not mounted. Calling scripts are responsible to unmount when done if another script might need a different USB drive. if ! grep -q /media /proc/mounts ; then stat -c %N /sys/block/sd* | grep usb | cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" > /tmp/usb_block_devices - #In case CONFIG_USB_BOOT_DEV was just a secondary device specified in board configuration and found, add it to the list - stat -c %N $CONFIG_USB_BOOT_DEV | grep -v usb| cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" >> /tmp/usb_block_devices - devices=$(cat /tmp/usb_block_devices |uniq|sort) - echo "$devices" > /tmp/usb_block_devices if [ -z `cat /tmp/usb_block_devices` ]; then if [ -x /bin/whiptail ]; then whiptail --title 'USB Drive Missing' \ @@ -52,10 +48,6 @@ if ! grep -q /media /proc/mounts ; then fi sleep 1 stat -c %N /sys/block/sd* | grep usb | cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" > /tmp/usb_block_devices - #In case CONFIG_USB_BOOT_DEV was just a secondary device specified in board configuration and found, add it to the list - stat -c %N $CONFIG_USB_BOOT_DEV | grep -v usb| cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" >> /tmp/usb_block_devices - devices=$(cat /tmp/usb_block_devices |uniq|sort) - echo "$devices" > /tmp/usb_block_devices if [ -z `cat /tmp/usb_block_devices` ]; then if [ -x /bin/whiptail ]; then whiptail $CONFIG_ERROR_BG_COLOR --title 'ERROR: USB Drive Missing' \ From 1a55239507cb40c80be6f8075e3e280981d884f1 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Tue, 14 May 2019 19:47:39 -0400 Subject: [PATCH 43/91] WIP --- initrd/boot/oem | 0 initrd/etc/functions | 185 +++++++++++++++++++++++-------- initrd/media/oem-provisioning | 198 ++++++++++++++++++++++++++++++++++ 3 files changed, 336 insertions(+), 47 deletions(-) create mode 100644 initrd/boot/oem create mode 100644 initrd/media/oem-provisioning diff --git a/initrd/boot/oem b/initrd/boot/oem new file mode 100644 index 000000000..e69de29bb diff --git a/initrd/etc/functions b/initrd/etc/functions index cccad285a..9f0ffdf4e 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -317,90 +317,181 @@ read_oem_file() /bin/mount-usb rw || warn "Unable to mount USB device. Continuing" if [ -e /media/oem-provisioning ]; then oem_gpg_Admin_PIN=$(grep "^oem_gpg_Admin_PIN=" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_gpg_Admin_PIN" ] && [ $(echo "$oem_gpg_Admin_PIN" | wc -l ) -eq 1 ]; then - export oem_gpg_Admin_PIN="$oem_gpg_Admin_PIN" + oem_gpg_Admin_PIN_count=$(echo "$oem_gpg_Admin_PIN" | wc -l ) + if [ -n "$oem_gpg_Admin_PIN" ]; then + if [ $oem_gpg_Admin_PIN_count -eq 1 ]; then + export oem_gpg_Admin_PIN="$oem_gpg_Admin_PIN" + elif [ $oem_gpg_Admin_PIN_count -gt 1 ]; then + warn "Multiple 'oem_gpg_Admin_PIN=' statements found. None retained." + unset oem_gpg_Admin_PIN + error=1 + fi else - warn "Multiple 'oem_gpg_Admin_PIN=' statements found. None retained." - unset oem_gpg_Admin_PIN - error=1 + warn "No 'oem_gpg_Admin_PIN=' statement found." + prompt_user_provisioning=1 fi - + oem_gpg_User_PIN=$(grep "^oem_gpg_User_PIN=" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_gpg_User_PIN" ] && [ $(echo "$oem_gpg_User_PIN" | wc -l ) -eq 1 ]; then - export oem_gpg_User_PIN="$oem_gpg_User_PIN" + oem_gpg_User_PIN_count=$(echo "$oem_gpg_User_PIN" | wc -l ) + if [ -n "$oem_gpg_User_PIN" ]; then + if [ $oem_gpg_User_PIN_count -eq 1 ]; then + export oem_gpg_User_PIN="$oem_gpg_User_PIN" + elif [ $oem_gpg_User_PIN_count -gt 1 ]; then + warn "Multiple 'oem_gpg_Admin_PIN=' statements found. None retained." + unset oem_gpg_User_PIN + error=1 + fi else - warn "Multiple 'oem_gpg_User_PIN=' statements found. None retained." - unset oem_gpg_User_PIN - error=1 + warn "No 'oem_gpg_User_PIN=' statement found." + prompt_user_provisioning=1 fi oem_gpg_real_name=$(grep "^oem_gpg_real_name=" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_gpg_real_name" ] && [ $(echo "$oem_gpg_real_name" | wc -l ) -eq 1 ]; then - export oem_gpg_real_name="$oem_gpg_real_name" + oem_gpg_real_name_count=$(echo "$oem_gpg_real_name" | wc -l ) + if [ -n "$oem_gpg_real_name" ]; then + if [ $oem_gpg_real_name_count -eq 1 ]; then + export oem_gpg_real_name="$oem_gpg_real_name" + elif [ $oem_gpg_real_name_count -gt 1 ]; then + warn "Multiple 'oem_gpg_real_name=' statements found. None retained." + unset oem_gpg_real_name + error=1 + fi else - warn "Multiple 'oem_gpg_real_name=' statements found. None retained." - unset oem_gpg_real_name - error=1 + warn "No 'oem_gpg_real_name=' statement found." + prompt_user_provisioning=1 fi oem_gpg_email=$(grep "^oem_gpg_email=" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_gpg_email" ] && [ $(echo "$oem_gpg_email" | wc -l ) -eq 1 ]; then - export oem_gpg_email="$oem_gpg_email" + oem_gpg_email_count=$(echo "$oem_gpg_email" | wc -l ) + if [ -n "$oem_gpg_email" ]; then + if [ $oem_gpg_email_count -eq 1 ]; then + export oem_gpg_email="$oem_gpg_email" + elif [ $oem_gpg_email_count -gt 1 ]; then + warn "Multiple 'oem_gpg_email=' statements found. None retained." + unset oem_gpg_email + error=1 + fi else - warn "Multiple 'oem_gpg_email=' statements found. None retained." - unset oem_gpg_email - error=1 + warn "No 'oem_gpg_email=' statement found." + prompt_user_provisioning=1 fi oem_gpg_comment=$(grep "^oem_gpg_comment=" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_gpg_comment" ] && [ $(echo "$oem_gpg_comment" | wc -l ) -eq 1 ]; then - export oem_gpg_comment="$oem_gpg_comment" + oem_gpg_comment_count=$(echo "$oem_gpg_comment" | wc -l ) + if [ -n "$oem_gpg_comment" ]; then + if [ $oem_gpg_comment_count -eq 1 ]; then + export oem_gpg_comment="$oem_gpg_comment" + elif [ $oem_gpg_comment -gt 1 ]; then + warn "Multiple 'oem_gpg_comment=' statements found. None retained." + unset oem_gpg_comment + error=1 + fi else - warn "Multiple 'oem_gpg_comment=' statements found. None retained." - unset oem_gpg_comment - error=1 + warn "No 'oem_gpg_comment=' statement found." + prompt_user_provisioning=1 fi oem_luks_actual_Disk_Recovery_Key=$(grep "^oem_luks_actual_Disk_Recovery_Key=" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_luks_actual_Disk_Recovery_Key" ] && [ $(echo "$oem_luks_actual_Disk_Recovery_Key" | wc -l ) -eq 1 ]; then - export oem_luks_actual_Disk_Recovery_Key="$oem_luks_actual_Disk_Recovery_Key" + oem_luks_actual_Disk_Recovery_Key_count=$(echo "$oem_luks_actual_Disk_Recovery_Key" | wc -l ) + if [ -n "$oem_luks_actual_Disk_Recovery_Key" ]; then + if [ $oem_luks_actual_Disk_Recovery_Key_count -eq 1 ]; then + export oem_luks_actual_Disk_Recovery_Key="$oem_luks_actual_Disk_Recovery_Key" + elif [ $oem_luks_actual_Disk_Recovery_Key_count -gt 1 ]; then + warn "Multiple 'oem_luks_actual_Disk_Recovery_Key=' statements found. None retained." + unset oem_luks_actual_Disk_Recovery_Key + error=1 + fi else - warn "Multiple 'oem_luks_actual_Disk_Recovery_Key=' statements found. None retained." - unset oem_luks_actual_Disk_Recovery_Key - error=1 + warn "No 'oem_luks_actual_Disk_Recovery_Key=' statement found." + prompt_user_provisioning=1 fi oem_luks_new_Disk_Recovery_Key=$(grep "^oem_luks_new_Disk_Recovery_Key=" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_luks_new_Disk_Recovery_Key" ] && [ $(echo "$oem_luks_new_Disk_Recovery_Key" | wc -l ) -eq 1 ]; then - export oem_luks_new_Disk_Recovery_Key="$oem_luks_new_Disk_Recovery_Key" + oem_luks_new_Disk_Recovery_Key_count=$(echo "$oem_luks_new_Disk_Recovery_Key" | wc -l ) + if [ -n "$oem_luks_new_Disk_Recovery_Key" ]; then + if [ $oem_luks_new_Disk_Recovery_Key_count -eq 1 ]; then + export oem_luks_new_Disk_Recovery_Key="$oem_luks_new_Disk_Recovery_Key" + elif [ $oem_luks_new_Disk_Recovery_Key_count -gt 1 ]; then + warn "Multiple 'oem_luks_new_Disk_Recovery_Key=' statements found. None retained." + unset oem_luks_new_Disk_Recovery_Key + error=1 + fi else - warn "Multiple 'oem_luks_new_Disk_Recovery_Key=' statements found. None retained." - unset oem_luks_new_Disk_Recovery_Key - error=1 + warn "No 'oem_luks_new_Disk_Recovery_Key=' statement found." + prompt_user_provisioning=1 fi oem_luks_Disk_Unlock_Key=$(grep "^oem_luks_Disk_Unlock_Key=" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_luks_Disk_Unlock_Key" ] && [ $(echo "$oem_luks_Disk_Unlock_Key" | wc -l ) -eq 1 ]; then - export oem_luks_Disk_Unlock_Key="$oem_luks_Disk_Unlock_Key" + oem_luks_Disk_Unlock_Key_count=$(echo "$oem_luks_Disk_Unlock_Key" | wc -l ) + if [ -n "$oem_luks_Disk_Unlock_Key" ]; then + if [ $oem_luks_Disk_Unlock_Key_count -eq 1 ]; then + export oem_luks_Disk_Unlock_Key="$oem_luks_Disk_Unlock_Key" + elif [ $oem_luks_Disk_Unlock_Key_count -gt 1 ]; then + warn "Multiple 'oem_luks_Disk_Unlock_Key=' statements found. None retained." + unset oem_luks_Disk_Unlock_Key + error=1 + fi else - warn "Multiple 'oem_luks_Disk_Unlock_Key=' statements found. None retained." - unset oem_luks_Disk_Unlock_Key - error=1 + warn "No 'oem_luks_Disk_Unlock_Key=' statement found." + prompt_user_provisioning=1 fi oem_TPM_Owner_Password=$(grep "^oem_TPM_Owner_Password=" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_TPM_Owner_Password" ] && [ $(echo "$oem_TPM_Owner_Password" | wc -l ) -eq 1 ]; then - export oem_TPM_Owner_Password="$oem_TPM_Owner_Password" + oem_TPM_Owner_Password_count=$(echo "$oem_TPM_Owner_Password" | wc -l ) + if [ -n "$oem_TPM_Owner_Password" ]; then + if [ $oem_TPM_Owner_Password_count -eq 1 ]; then + export oem_TPM_Owner_Password="$oem_TPM_Owner_Password" + elif [ $oem_TPM_Owner_Password_count -gt 1 ]; then + warn "Multiple 'oem_TPM_Owner_Password=' statements found. None retained." + unset oem_TPM_Owner_Password + error=1 + fi else - warn "Multiple 'oem_TPM_Owner_Password=' statements found. None retained." - unset oem_TPM_Owner_Password - error=1 + warn "No 'oem_TPM_Owner_Password=' statement found." + prompt_user_provisioning=1 fi - + if [ -n $error ] && [ "$error" -eq 1 ]; then recovery "Please run 'vi /media/oem-provisioning' to correct previous warnings. ('i': insert, modify, 'Esc' key, then ':wq', 'Enter' key, then 'unmount /media' and 'reboot'." fi + if [ -n $prompt_user_provisioning ] && [ "$prompt_user_provisioning" -eq 1 ];then + #TODO prompt for provisioning of unfilled variables + #TODO: Put provisioning tracker into /boot/oem + #TODO: Put /media/provisioning provisioning partition tracker into /boot/oem + + for to_provision in oem_gpg_Admin_PIN oem_gpg_User_PIN oem_gpg_real_name oem_gpg_email oem_gpg_comment oem_luks_actual_Disk_Recovery_Key oem_luks_new_Disk_Recovery_Key oem_luks_Disk_Unlock_Key + do + iterator=$(eval echo \$$to_provision) + debug "1-to_provision = $to_provision" + debug "2-iterator = $iterator" + + to_provision_cnt="$to_provision_count" + debug "3-to_provision_cnt = $to_provision_cnt" + + if [ "$to_provision_cnt" -eq 0 ];then + + if [ "$iterator" == "oem_gpg_Admin_PIN" ] ;then + echo "We have limitations for Admin Pin" + echo "Value of oem_gpg_Admin_PIN = $(echo eval \$$iterator)" + debug "check above" + fi + + fi + done + + recovery "this is where we would prompt user to provision once automatic provisioning of secrets in the EOM reownership Wizard." + + #Could be a for loop of all undefined variables? + #Do prompt of specifc constraints + #GPG Admin: no space. + #Admin PIN: >8 chars. User Pins > 6 chars + #GPG email format validation + #GPG Name > 5 char < 30 + #Validate double prompt validated input + #Store by appending to /media/oem-provisioning + fi + export oem_configuration_read=1 umount /media fi diff --git a/initrd/media/oem-provisioning b/initrd/media/oem-provisioning new file mode 100644 index 000000000..459457cd6 --- /dev/null +++ b/initrd/media/oem-provisioning @@ -0,0 +1,198 @@ +########### +# OEM # +########### +# To activate OEM reownership wizard, under Heads recovery console, do: +# mount /boot +# mount -o remount,rw /boot +# echo "oem_name=COMPANY NAME" > /boot/oem +# mount -o remount,ro /boot +# reboot +# +# To activate OEM automatic provisioning, the content of this file needs to be found by Heads under: +# /media/oem-provisioning +# By default, the USB drive is mounted from /dev/sdb1 but "mount-usb" will find the usb drive and mount it under /media +# +# Replace variables content with your own! +# +#The following needs to be put in /boot/oem for OEM name to be shown at OEM Reownership wizard first screen. Else it is going to be "your OEM". +#oem_name=Insurgo Open Technologies +# +#On a recovery shell, type the UP arrow key until you reach top of the history buffer. A command is proposed for you to change "YOUR COMPANY" +# to your own. The hardware is then ready to ship and the wizard will accompany the user in reowning the hardware and OEM secrets on next reboot. +# +# You should invite the user into using "generate_diceware-eom-provisioning.sh" script in the current directory, +# which uses diceware to prefeed "oem-provisioning.generated" with proper secrets. +# The user would then need to put that file under "oem-provisioning" on the root of a dedicated USB drive and connect on first boot of +# received hardware to reduce user errors and friction of having to enter those secrets manually. + +######### +# GPG # +######### +# GPG card function in Heads: +# The Librem Key/NitroKey is a traditional GPG card added with HMAC-based One-time Password (HOTP) which permits +# to seal integrity measurements into the GPG card memory. +# +# As a functional result, at each boot, the card will flash its LED green if the measured boot integrity +# is atttested or red in case of a mismatch. This provable security measure is called tamper-evidence and +# informs the user that the Firmware (BIOS chips content) has been tampered with, or modified, and doesn't +# match expected measurements expected by the Trusted Platform Module (TPM) and validated by the GPG card. +# +# Heads traditionally stores Trusted Module Platform (TPM) Time-based One-time Password (TOTP) code in a +# smartphone through the scanning of a QR code into an OTP authenticator application when the TPM is reowned or +# when a firmware update is applied. Through the reownership process, the firmware will be modified by inserting +# public PGP key into the firmware, which will invalidate measurements and require the TOTP/HOTP to be resealed. +# The TPM itself will be reowned by the user, requesting him to set a passphrase. +# +# *** You should use both TOTP/HOTP so you can still validate attested integiryt in case your GPG card gets lost *** +# +# HOTP/TOTP are functionally similar, while the Librem Key/Nitrokey permits to validate integrity visually in an +# instant without having to unlock the smartphone, open the OTP application and verify that a 6 digits code there +# is the same that is shown on the screen. +# HOTP Librem Key/Nitrokey feature is complementory to the TOTP and shares the same codebase. +# +# Heads also depends on the GPG card to store used private key outside of prying eyes, securely stored on the +# Smartcard. When factory resetting the card, only the public key is inserted into the rom, which is used +# to automatically validate the integiryt of /boot files through checksuming and validating the the result +# matches what is signed with the private key on the GPG card. +# +# Heads will warn the user each time boot configuration changes. +# That will happen when the Operating System applies core system updates (Xen, Kernel, initrd (drivers) +# and grub configuration) while notifying the user of any addition/supression of files expected to be found +# in the /boot partition. +# +# GPG usage in Heads: +# Heads will prompt the user for: +# User PIN: +# Sign boot configuration changes. +# Admin PIN: +# Seal Firmware changes through HOTP +# +# IMPORTANT: +# The user should always reboot the system and sign configuration changes as soon as possible after system upgrades +# to attest the responsibility and ownership of the changes. +# +# The user should always be cautious about TOTP/HOTP errors if he didn't update the firmware himself. +# +# Heads primary goal is to attest of the integrity of the firmware and /boot files. +# That integrity attestation is based on those two practices that REQUIRES TO BE FOLLOWED. +# +# PIN Notes: GPG PINs are protected in the SmartCard. After 3 bad attempts, the SmartCard locks that account. +# When the User PIN is locked, the Admin PIN can be used to unlock User PIN. +# When the Admin PIN is locked, a Reset Code can be used to unlock Admin PIN. +# This is not provisioned by default. You will have to set one manually yourself. +# +# You can define an additional "Reset Code" to reset the Admin PIN manually by doing: +# gpg --card-edit +# admin +# passwd +# 4 - set the Reset Code +# Type Admin PIN +# +#GPG SmartCard desired Admin PIN to provision GPG factory reset. +# Admin PIN manages Admin functions of the card through gpg --edit-card admin functions, +# In Heads, the Admin PIN is required to seal HOTP secret into NitroKey/Librem Key when firmware has been modified. +# +# NOTES: If the GPG card is lost, the user won't be able to seal firmware changes through HOTP. +# Size constaints: minimum 8 characters, maximum 20 characters, WITHOUT SPACES! +# (Else HOTP cannot be sealed. It's a seal-libremkey limitation) +# No need to go crazy here. Remember that 3 bad attempts locks the account. One or two Diceware words are enough. +# Use KeepassXC password manager or something like https://www.rempe.us/diceware/#eff +oem_gpg_Admin_PIN=InsurgoTech +# +#GPG SmartCard desired User PIN to provision GPG factory reset. +# User PIN manages user functions of the card. It is used to encrypt files and e-mails, sign files and e-mails +# and authenticate the user in daily operations when used in combination with the public key generated. +# That public key needs to be kept, as it is impossible to export it from the smartcard. +# In Heads, the User PIN is required to sign boot configuration changes. +# At each boot, the imported public key counterpart is used to validate the checksums of the files signed with the card. +# +# NOTES: If the GPG card is lost, the user won't be able to sign system changes. +# Size constaints: minimum 6 characters, maximum 20 characters +# No need to go crazy here. Remember that 3 bad attempts locks the account. One or two Diceware words are enough. +# Use KeepassXC password manager or something like https://www.rempe.us/diceware/#eff +oem_gpg_User_PIN=Insurgo +#GPG SmartCard desired Real Name to provision GPG factory reset. +# This will be used to construct the ID of the public key: "Real Name (Comment) email@address.org" +# +# Size constaints: minimum 5 characters. +oem_gpg_real_name=Insurgo Integrity Delivered Attestation Attestation Librem Key +#GPG SmartCard desired E-mail address to provision GPG factory reset. +# This will be used to construct the ID of the public key: "Real Name (Comment) email@address.org" +# Note that some services requires that e-mail address to be real and will send an e-mail to validate it. +# If you intend to use the GPG card to encrypt/sign e-mails, this is a good idea to provide main e-mail account here. +oem_gpg_email=insurgo@riseup.net +#GPG SmartCard desired Comment to provision GPG factory reset. +# This will be used to construct the ID of the public key: "Real Name (Comment) email@address.org" +# If you have multiple cards associated with the same E-mail address, this is a good place to name it's usage difference +oem_gpg_comment=FACTORY RESET ME + +########## +# LUKS # +########## +# LUKS containers are used in Linux to encrypt whole filesystems. +# The whole idea behind OEM reownership depends on the LUKS reencryption of the container from the user when hardware +# is received. Otherwise, the OEM would know the cloned image LUKS Disk Recovery Key and could hand it to authorities. +# This provisioning wizard starts by asking you to enter the actual LUKS Disk Recovery Key passphrase to reencrypt the +# container completely, before changing it's passphrase with user selected one. +# +# This LUKS Disk Recovery Key, if provided by the OEM **** SHOULD NOT BE MODIFIED ***** +oem_luks_actual_Disk_Recovery_Key=InsurgoTech +# This is where you want to define your new Disk Recovery Key passphrase, which will be associated to the reencrypted LUKS +# container after the OEM wizard is over and become the Disk Recovery Key passphrase. +# +# This provisioning wizard continues by asking you to enter the desired LUKS Disk Recovery Key passphrase and changes +# it. +# +# The Disk Recovery Key will be prompted to the user in the following cases: +# 1-Every boot if no Disk Unlock Key was added to the TPM (NOT RECOMMENDED! could be captured and used on cloned disk) +# 2-If the TPM fails (Hardware failure) +# 3-If the firmware has been tampered with/upgraded/modified by the user +# +# NOTES: If the Disk Recovery Key Passphrase is lost, the user won't be able to set a new Disk Unlock Key. +# More importantly, in the case of a Operating System core update (Xen, Kernel, initrd (drivers) or grub config, +# the Default Boot option will be invalidated, and the only way to boot the system will be by typing this +# Disk Recovery Key Passphrase. ********** CHOOSE IT CAREFULLY SO YOU CAN EASILY REMEMBER IT *********** +# +# Size constaints: select a Diceware passphrase of at least 3 words. 6 is better. +# No need to go crazy here. It's better to have a shorter but strong passphrase you remember and not type often +# then a strong passphrase that locks you out of the system and requires you to reinstall. +# Use KeepassXC password manager or something alike https://www.rempe.us/diceware/#eff +oem_luks_new_Disk_Recovery_Key=InsurgoTech +# Disk Unlock Key Passphrase is the passphrase the user will be required to type under Heads to start the system. +# +# The Disk Unlock Key is another security feature enforced by Heads that makes your computer more trustworthy. +# The Disk Unlock Key is released by the Trusted Platform Module (TPM), a cryptographic component on which +# depends Heads to measure and attest firmware integrity, and released only if the measurements of the firmware +# are intact (sealed). In the case the firmware has been modified, that the user lost/forgot his GPG card, +# the Disk Unlock key passphrase will refuse to release the actual Disk Unlock Key and will not boot, unless +# you to type the Disk Recovery Key passphrase. +# +# Heads would not be able to unseal neither TOTP/HOTP in case measurements mismatche and will warn the user. +# +# The Disk Unlock Key passphrase will also not be able to unlock the disk if the LUKS header is not +# consistent with what was sealed into the TPM when selecting a default boot option. +# +# Functionnaly, selecting a default boot option and setting a Disk Unlock Key is a good security measure against +# prying eyes, let them be camera recording or over the shoulder passphrase capture. +# Since that Key is bounded with firmware integrity measurements from the TPM, that passphrase is bound to this +# computer only. +# +# A third party which would clone the disk and attempt to access its content later would succeed only if +# Disk Recovery Key passphrase was typed, not the Disk Unlock Key passphrase. +# +# Size constaints: Best is to select a Diceware passphrase of at least 4 words. 6+ is better. +# Use KeypassXC password manager or something like https://www.rempe.us/diceware/#eff +# No need to go crazy here. An attacker would have 3 attempts at a time when booting Heads. +# Use KeepassXC password manager or something like https://www.rempe.us/diceware/#eff +# You will be prompted to change this passphrase at every core Operating System upgrades since the default boot +# option will be modified. +oem_luks_Disk_Unlock_Key=Insurgo + +################################### +# Trusted Platform Module (TPM) # +################################### +# The TPM passphrase is required when sealing the Disk Unlock Key when selecting a new default boot option, +# combined with the GPG User PIN. +# +# It is recommended to reuse GPG Admin Passphrase/Password here, to not unecessarily multiply secrets to remember. +#oem_TPM_Owner_Password=InsurgoTech From 36d51b74c641642b01cad77aa909c996f1b0bce6 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Tue, 14 May 2019 19:47:39 -0400 Subject: [PATCH 44/91] WIP --- initrd/etc/functions | 187 ++++++++++++++++++++++++++++++++----------- 1 file changed, 140 insertions(+), 47 deletions(-) diff --git a/initrd/etc/functions b/initrd/etc/functions index cccad285a..a4d9065e2 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -317,90 +317,183 @@ read_oem_file() /bin/mount-usb rw || warn "Unable to mount USB device. Continuing" if [ -e /media/oem-provisioning ]; then oem_gpg_Admin_PIN=$(grep "^oem_gpg_Admin_PIN=" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_gpg_Admin_PIN" ] && [ $(echo "$oem_gpg_Admin_PIN" | wc -l ) -eq 1 ]; then - export oem_gpg_Admin_PIN="$oem_gpg_Admin_PIN" + oem_gpg_Admin_PIN_count=$(echo "$oem_gpg_Admin_PIN" | wc -l ) + if [ -n "$oem_gpg_Admin_PIN" ]; then + if [ $oem_gpg_Admin_PIN_count -eq 1 ]; then + export oem_gpg_Admin_PIN="$oem_gpg_Admin_PIN" + elif [ $oem_gpg_Admin_PIN_count -gt 1 ]; then + warn "Multiple 'oem_gpg_Admin_PIN=' statements found. None retained." + unset oem_gpg_Admin_PIN + error=1 + fi else - warn "Multiple 'oem_gpg_Admin_PIN=' statements found. None retained." - unset oem_gpg_Admin_PIN - error=1 + warn "No 'oem_gpg_Admin_PIN=' statement found." + prompt_user_provisioning=1 fi - + oem_gpg_User_PIN=$(grep "^oem_gpg_User_PIN=" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_gpg_User_PIN" ] && [ $(echo "$oem_gpg_User_PIN" | wc -l ) -eq 1 ]; then - export oem_gpg_User_PIN="$oem_gpg_User_PIN" + oem_gpg_User_PIN_count=$(echo "$oem_gpg_User_PIN" | wc -l ) + if [ -n "$oem_gpg_User_PIN" ]; then + if [ $oem_gpg_User_PIN_count -eq 1 ]; then + export oem_gpg_User_PIN="$oem_gpg_User_PIN" + elif [ $oem_gpg_User_PIN_count -gt 1 ]; then + warn "Multiple 'oem_gpg_Admin_PIN=' statements found. None retained." + unset oem_gpg_User_PIN + error=1 + fi else - warn "Multiple 'oem_gpg_User_PIN=' statements found. None retained." - unset oem_gpg_User_PIN - error=1 + warn "No 'oem_gpg_User_PIN=' statement found." + prompt_user_provisioning=1 fi oem_gpg_real_name=$(grep "^oem_gpg_real_name=" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_gpg_real_name" ] && [ $(echo "$oem_gpg_real_name" | wc -l ) -eq 1 ]; then - export oem_gpg_real_name="$oem_gpg_real_name" + oem_gpg_real_name_count=$(echo "$oem_gpg_real_name" | wc -l ) + if [ -n "$oem_gpg_real_name" ]; then + if [ $oem_gpg_real_name_count -eq 1 ]; then + export oem_gpg_real_name="$oem_gpg_real_name" + elif [ $oem_gpg_real_name_count -gt 1 ]; then + warn "Multiple 'oem_gpg_real_name=' statements found. None retained." + unset oem_gpg_real_name + error=1 + fi else - warn "Multiple 'oem_gpg_real_name=' statements found. None retained." - unset oem_gpg_real_name - error=1 + warn "No 'oem_gpg_real_name=' statement found." + prompt_user_provisioning=1 fi oem_gpg_email=$(grep "^oem_gpg_email=" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_gpg_email" ] && [ $(echo "$oem_gpg_email" | wc -l ) -eq 1 ]; then - export oem_gpg_email="$oem_gpg_email" + oem_gpg_email_count=$(echo "$oem_gpg_email" | wc -l ) + if [ -n "$oem_gpg_email" ]; then + if [ $oem_gpg_email_count -eq 1 ]; then + export oem_gpg_email="$oem_gpg_email" + elif [ $oem_gpg_email_count -gt 1 ]; then + warn "Multiple 'oem_gpg_email=' statements found. None retained." + unset oem_gpg_email + error=1 + fi else - warn "Multiple 'oem_gpg_email=' statements found. None retained." - unset oem_gpg_email - error=1 + warn "No 'oem_gpg_email=' statement found." + prompt_user_provisioning=1 fi oem_gpg_comment=$(grep "^oem_gpg_comment=" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_gpg_comment" ] && [ $(echo "$oem_gpg_comment" | wc -l ) -eq 1 ]; then - export oem_gpg_comment="$oem_gpg_comment" + oem_gpg_comment_count=$(echo "$oem_gpg_comment" | wc -l ) + if [ -n "$oem_gpg_comment" ]; then + if [ $oem_gpg_comment_count -eq 1 ]; then + export oem_gpg_comment="$oem_gpg_comment" + elif [ $oem_gpg_comment -gt 1 ]; then + warn "Multiple 'oem_gpg_comment=' statements found. None retained." + unset oem_gpg_comment + error=1 + fi else - warn "Multiple 'oem_gpg_comment=' statements found. None retained." - unset oem_gpg_comment - error=1 + warn "No 'oem_gpg_comment=' statement found." + prompt_user_provisioning=1 fi oem_luks_actual_Disk_Recovery_Key=$(grep "^oem_luks_actual_Disk_Recovery_Key=" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_luks_actual_Disk_Recovery_Key" ] && [ $(echo "$oem_luks_actual_Disk_Recovery_Key" | wc -l ) -eq 1 ]; then - export oem_luks_actual_Disk_Recovery_Key="$oem_luks_actual_Disk_Recovery_Key" + oem_luks_actual_Disk_Recovery_Key_count=$(echo "$oem_luks_actual_Disk_Recovery_Key" | wc -l ) + if [ -n "$oem_luks_actual_Disk_Recovery_Key" ]; then + if [ $oem_luks_actual_Disk_Recovery_Key_count -eq 1 ]; then + export oem_luks_actual_Disk_Recovery_Key="$oem_luks_actual_Disk_Recovery_Key" + elif [ $oem_luks_actual_Disk_Recovery_Key_count -gt 1 ]; then + warn "Multiple 'oem_luks_actual_Disk_Recovery_Key=' statements found. None retained." + unset oem_luks_actual_Disk_Recovery_Key + error=1 + fi else - warn "Multiple 'oem_luks_actual_Disk_Recovery_Key=' statements found. None retained." - unset oem_luks_actual_Disk_Recovery_Key - error=1 + warn "No 'oem_luks_actual_Disk_Recovery_Key=' statement found." + prompt_user_provisioning=1 fi oem_luks_new_Disk_Recovery_Key=$(grep "^oem_luks_new_Disk_Recovery_Key=" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_luks_new_Disk_Recovery_Key" ] && [ $(echo "$oem_luks_new_Disk_Recovery_Key" | wc -l ) -eq 1 ]; then - export oem_luks_new_Disk_Recovery_Key="$oem_luks_new_Disk_Recovery_Key" + oem_luks_new_Disk_Recovery_Key_count=$(echo "$oem_luks_new_Disk_Recovery_Key" | wc -l ) + if [ -n "$oem_luks_new_Disk_Recovery_Key" ]; then + if [ $oem_luks_new_Disk_Recovery_Key_count -eq 1 ]; then + export oem_luks_new_Disk_Recovery_Key="$oem_luks_new_Disk_Recovery_Key" + elif [ $oem_luks_new_Disk_Recovery_Key_count -gt 1 ]; then + warn "Multiple 'oem_luks_new_Disk_Recovery_Key=' statements found. None retained." + unset oem_luks_new_Disk_Recovery_Key + error=1 + fi else - warn "Multiple 'oem_luks_new_Disk_Recovery_Key=' statements found. None retained." - unset oem_luks_new_Disk_Recovery_Key - error=1 + warn "No 'oem_luks_new_Disk_Recovery_Key=' statement found." + prompt_user_provisioning=1 fi oem_luks_Disk_Unlock_Key=$(grep "^oem_luks_Disk_Unlock_Key=" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_luks_Disk_Unlock_Key" ] && [ $(echo "$oem_luks_Disk_Unlock_Key" | wc -l ) -eq 1 ]; then - export oem_luks_Disk_Unlock_Key="$oem_luks_Disk_Unlock_Key" + oem_luks_Disk_Unlock_Key_count=$(echo "$oem_luks_Disk_Unlock_Key" | wc -l ) + if [ -n "$oem_luks_Disk_Unlock_Key" ]; then + if [ $oem_luks_Disk_Unlock_Key_count -eq 1 ]; then + export oem_luks_Disk_Unlock_Key="$oem_luks_Disk_Unlock_Key" + elif [ $oem_luks_Disk_Unlock_Key_count -gt 1 ]; then + warn "Multiple 'oem_luks_Disk_Unlock_Key=' statements found. None retained." + unset oem_luks_Disk_Unlock_Key + error=1 + fi else - warn "Multiple 'oem_luks_Disk_Unlock_Key=' statements found. None retained." - unset oem_luks_Disk_Unlock_Key - error=1 + warn "No 'oem_luks_Disk_Unlock_Key=' statement found." + prompt_user_provisioning=1 fi oem_TPM_Owner_Password=$(grep "^oem_TPM_Owner_Password=" /media/oem-provisioning | cut -d "=" -f2) - if [ -n "$oem_TPM_Owner_Password" ] && [ $(echo "$oem_TPM_Owner_Password" | wc -l ) -eq 1 ]; then - export oem_TPM_Owner_Password="$oem_TPM_Owner_Password" + oem_TPM_Owner_Password_count=$(echo "$oem_TPM_Owner_Password" | wc -l ) + if [ -n "$oem_TPM_Owner_Password" ]; then + if [ $oem_TPM_Owner_Password_count -eq 1 ]; then + export oem_TPM_Owner_Password="$oem_TPM_Owner_Password" + elif [ $oem_TPM_Owner_Password_count -gt 1 ]; then + warn "Multiple 'oem_TPM_Owner_Password=' statements found. None retained." + unset oem_TPM_Owner_Password + error=1 + fi else - warn "Multiple 'oem_TPM_Owner_Password=' statements found. None retained." - unset oem_TPM_Owner_Password - error=1 + warn "No 'oem_TPM_Owner_Password=' statement found." + prompt_user_provisioning=1 fi - + if [ -n $error ] && [ "$error" -eq 1 ]; then recovery "Please run 'vi /media/oem-provisioning' to correct previous warnings. ('i': insert, modify, 'Esc' key, then ':wq', 'Enter' key, then 'unmount /media' and 'reboot'." fi + if [ -n $prompt_user_provisioning ] && [ "$prompt_user_provisioning" -eq 1 ];then + #TODO prompt for provisioning of unfilled variables + #TODO: Put provisioning tracker into /boot/oem + #TODO: Put /media/provisioning provisioning partition tracker into /boot/oem + + for to_provision in oem_gpg_Admin_PIN oem_gpg_User_PIN oem_gpg_real_name oem_gpg_email oem_gpg_comment oem_luks_actual_Disk_Recovery_Key oem_luks_new_Disk_Recovery_Key oem_luks_Disk_Unlock_Key + do + indirector=$(eval echo \$$to_provision) + debug "1-to_provision = $to_provision" + debug "2-indirector = $indirector" + + to_provision_cnt="$indirector" "_count" + to_provision_cnt_indirector=$(eval echo \$$to_provision_cnt) + debug "3-to_provision_cnt = $to_provision_cnt" + debug "4-to_provision_cnt_indirector= $to_provision_cnt_indirector" + + if [ "$to_provision_cnt_indirector" -eq 0 ];then + + if [ "$iterator" == "oem_gpg_Admin_PIN" ] ;then + echo "We have limitations for Admin Pin" + echo "Value of oem_gpg_Admin_PIN = $(echo eval \$$iterator)" + debug "check above" + fi + + fi + done + + recovery "this is where we would prompt user to provision once automatic provisioning of secrets in the EOM reownership Wizard." + + #Could be a for loop of all undefined variables? + #Do prompt of specifc constraints + #GPG Admin: no space. + #Admin PIN: >8 chars. User Pins > 6 chars + #GPG email format validation + #GPG Name > 5 char < 30 + #Validate double prompt validated input + #Store by appending to /media/oem-provisioning + fi + export oem_configuration_read=1 umount /media fi From eb15108e28d10760ce4b670233f3fe07ab8debc4 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Thu, 23 May 2019 12:45:34 -0400 Subject: [PATCH 45/91] Merge branch 'master' of https://github.com/osresearch/heads into HEAD --- Makefile | 1 + README.md | 36 +++++------------------------------- blobs/x220/readme.md | 2 +- config/linux-x230.config | 6 +----- 4 files changed, 8 insertions(+), 37 deletions(-) diff --git a/Makefile b/Makefile index 3cc193a32..74818a110 100644 --- a/Makefile +++ b/Makefile @@ -231,6 +231,7 @@ define define_module = # this case, since we don't have a stable version to compare against. $(build)/$($1_base_dir)/.canary: git clone $($1_repo) "$(build)/$($1_base_dir)" + cd $(build)/$($1_base_dir) && git submodule update --init --checkout if [ -r patches/$1.patch ]; then \ ( cd $(build)/$($1_base_dir) ; patch -p1 ) \ < patches/$1.patch \ diff --git a/README.md b/README.md index aa2970eec..152679131 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,10 @@ significant frustration. More information is available in [the 33C3 presentation of building "Slightly more secure systems"](https://trmm.net/Heads_33c3). +Documentation +=== +Please refer to [Heads-wiki](https://github.com/osresearch/heads-wiki/blob/master/index.md) for your Heads' documentation needs. + Building heads === @@ -56,7 +60,7 @@ directory and include: * [Xen hypervisor](https://www.xenproject.org/) We also recommend installing [Qubes OS](https://www.qubes-os.org/), -although there Heads can `kexec` into any (?) Linux or +although there Heads can `kexec` into any Linux or [multiboot](https://www.gnu.org/software/grub/manual/multiboot/multiboot.html) kernel. @@ -67,41 +71,11 @@ Notes: * Builds are finally reproducible! The [reproduciblebuilds tag](https://github.com/osresearch/heads/issues?q=is%3Aopen+is%3Aissue+milestone%3Areproduciblebuilds) tracks any regressions. * Currently only tested in QEMU, the Thinkpad x230 and the Chell Chromebook. ** Xen and the TPM do not work in QEMU, so it is only for testing the `initrd` image. -* Booting Qubes requires patching Xen's real mode startup code -see `patches/xen-4.6.3.patch` and adding `no-real-mode` to start -of the Xen command line. Booting or installing Qubes is a bit hacky and needs to be documented. * Building for the Lenovo X220 requires binary blobs to be placed in the blobs/x220/ folder. See the readme.md file in that folder * Building for the Librem 13 v2/v3 or Librem 15 v3/v4 requires binary blobs to be placed in the blobs/librem_skl folder. See the readme.md file in that folder -Signing with GPG ---- -`gpgv` is a stripped down version of GPG that can be used to verify -signatures without extraneous libraries. This works well with the -Free Software workflow that we want to use. - - gpg --clearsign roothash - -The `roothash` and `roothash.sig` files can be embedded into the -HDD image and then extracted at firmware boot time: - - gpgv --keyring /trustedkeys.gpg roothash.sig roothash \ - || echo "FAILED" - -The `mount-boot` script is a start at doing this automatically. -There needs to be an empty block at the end of the partition -that includes a signed script to be executed; typically it will -contain the dm-verity parameters to build the `dmsetup` command -line to mount `/boot`. - -The boot script can't be stored in the boot filesystem since the -dm-verity hashes that protect the filesystem would need to have their -own hash pre-computed, which is not feasible with a good hashing -algorithm. You could store the hashes in the ROM, but that would -not allow upgrades without rewriting the ROM. - - coreboot console messages --- The coreboot console messages are stored in the CBMEM region diff --git a/blobs/x220/readme.md b/blobs/x220/readme.md index 1eeea5b47..ff682f3b6 100644 --- a/blobs/x220/readme.md +++ b/blobs/x220/readme.md @@ -23,4 +23,4 @@ The flash layout will be automatically adjusted and the ME image cleaned and tru You can now compile the image with: -make BOARD=x220 CONFIG=config/x220-generic.config +make BOARD=x220 diff --git a/config/linux-x230.config b/config/linux-x230.config index 353670dfb..2e6a9617f 100644 --- a/config/linux-x230.config +++ b/config/linux-x230.config @@ -222,14 +222,10 @@ CONFIG_NLS_ISO8859_1=y CONFIG_NLS_UTF8=y CONFIG_PRINTK_TIME=y CONFIG_BOOT_PRINTK_DELAY=y -CONFIG_DYNAMIC_DEBUG=y -CONFIG_DEBUG_INFO=y -CONFIG_DEBUG_INFO_DWARF4=y -CONFIG_GDB_SCRIPTS=y # CONFIG_ENABLE_WARN_DEPRECATED is not set # CONFIG_ENABLE_MUST_CHECK is not set CONFIG_FRAME_WARN=1024 -CONFIG_DEBUG_FS=y +# CONFIG_UNUSED_SYMBOLS is not set CONFIG_MAGIC_SYSRQ=y CONFIG_HARDLOCKUP_DETECTOR=y CONFIG_WQ_WATCHDOG=y From 39140d1e05f5b273ee38c6203645de0732063bdd Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Tue, 28 May 2019 11:30:05 -0400 Subject: [PATCH 46/91] Attempt to remove HZ errors with nohz=on which cut user inputs in my tests --- boards/qemu-coreboot/qemu-coreboot.config | 2 ++ config/coreboot-qemu.config | 1 + 2 files changed, 3 insertions(+) diff --git a/boards/qemu-coreboot/qemu-coreboot.config b/boards/qemu-coreboot/qemu-coreboot.config index 142c7f4c9..026aa2a24 100644 --- a/boards/qemu-coreboot/qemu-coreboot.config +++ b/boards/qemu-coreboot/qemu-coreboot.config @@ -49,6 +49,8 @@ export CONFIG_TPM=n export CONFIG_BOOT_DEV="/boot.img" export CONFIG_USB_BOOT_DEV="/media.img" +export CONFIG_BOOT_KERNEL_ADD="nohz=on" + #run: coreboot.intermediate run: diff --git a/config/coreboot-qemu.config b/config/coreboot-qemu.config index cfccf5269..78dd08a3e 100644 --- a/config/coreboot-qemu.config +++ b/config/coreboot-qemu.config @@ -13,5 +13,6 @@ CONFIG_CPU_MICROCODE_CBFS_GENERATE=y # CONFIG_CONSOLE_SERIAL is not set CONFIG_DEFAULT_CONSOLE_LOGLEVEL_6=y CONFIG_PAYLOAD_LINUX=y +CONFIG_LINUX_COMMAND_LINE="nohz=on" CONFIG_PAYLOAD_FILE="../../build/qemu-coreboot/bzImage" CONFIG_LINUX_INITRD="../../build/qemu-coreboot/initrd.cpio.xz" From 557d47cd761cf1ded2c6c88ce4b8cd5fb85b6315 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Tue, 28 May 2019 11:32:32 -0400 Subject: [PATCH 47/91] add "clear" command availability through busybox config change --- config/busybox.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/busybox.config b/config/busybox.config index ee7e7c778..f3416ec68 100644 --- a/config/busybox.config +++ b/config/busybox.config @@ -350,7 +350,7 @@ CONFIG_FEATURE_HUMAN_READABLE=y # Console Utilities # # CONFIG_CHVT is not set -# CONFIG_CLEAR is not set +CONFIG_CLEAR=y # CONFIG_DEALLOCVT is not set # CONFIG_DUMPKMAP is not set # CONFIG_FGCONSOLE is not set From faacaf743bb10f417c71c62a74fb75f66119d2d6 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Tue, 28 May 2019 11:33:34 -0400 Subject: [PATCH 48/91] OEM ReOwnership now proposes to generate missing /media/oem-provisioning secrets - Takes into consideration if TPM in BOARD config and if Disk Unlock Key is desired. - uses shuf and clear that were added in busybox - For each passphrase, randomly selected diceware passphrases are proposed -- For each of those passphrases, the user has the possibility to keep it (k), generate a new one (n) until one fits, or manually enter one (m) --- Manually entering one outputs 500 random words taken from the EFF diceware dictionary and outputs on screen, asking the user to select one creating an emotionaly bounding story. -- For each of those passphrases, a bare minimal length is enforced. GPG PINs are of two words, Disk Recovery passphrase, of 25 char, and TPM ownership copies GPG Admin selected PIN (Which is refused if it contains a space since HOTP validation can't take those) At the end of the provisioning phase, all "oem_" of env output are sorted and outputted into /media/oem-provisioning TODO: - Modify LUKS reencryption logic to also reencrypt OEM provided microsd card with new Disk Recovery Key passphrase - Put used microsd device to find /media/oem-provisioning into /boot/oem to not prompt the user to select OEM Provisioning media at each reboot until OEM ReOwnership Wizard ends -- Warns the user if that device is not a LUKS container --- initrd/etc/functions | 619 +++++++++++++++++++++++++++---------------- 1 file changed, 392 insertions(+), 227 deletions(-) diff --git a/initrd/etc/functions b/initrd/etc/functions index e86fa0dbf..c4ef90ad5 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -313,7 +313,7 @@ combine_configs() { } read_oem_file() { - #TODO: check if /boot/oem contains past USB disk and automount it. see tracing TODO below + #TODO: check if /boot/oem contains past microsd disk and automount it. see tracing TODO below oem_name=$(grep "oem_name" /boot/oem | awk -F '=' {'print $2'}) if [ -n "$oem_name" ]; then export oem_name="$oem_name" @@ -321,257 +321,360 @@ read_oem_file() oem_name="your OEM" export oem_name="$oem_name" fi + + if ! [ $(grep "no_automatic_provisioning" /boot/oem) ]; then + + echo "Mounting USB drive to provision OEM reownership from /media/oem-provisioning..." + /bin/mount-usb rw || warn "Unable to mount USB device. Continuing" + #By default, OEM should provide oem-provisioning file with at least "oem_luks_actual_Disk_Recovery_Key" defined and reach this point. + #If the user decides to not provision OEM through this file, that file will be deleted, and no_automatic_provisioning outputted in /boot/oem + + #ICI valider mount point + if [ -e /media/oem-provisioning ]; then + #TODO: trace mounted USB disk into /boot/oem + echo "Found /media/oem-provisioning. Parsing..." + oem_gpg_Admin_PIN=$(grep "^oem_gpg_Admin_PIN=" /media/oem-provisioning | cut -d "=" -f2) + oem_gpg_Admin_PIN_count=$(echo "$oem_gpg_Admin_PIN" | wc -l ) + if [ -n "$oem_gpg_Admin_PIN" ]; then + if [ $oem_gpg_Admin_PIN_count -eq 1 ]; then + export oem_gpg_Admin_PIN="$oem_gpg_Admin_PIN" + elif [ $oem_gpg_Admin_PIN_count -gt 1 ]; then + warn "Multiple 'oem_gpg_Admin_PIN=' statements found. None retained." + unset oem_gpg_Admin_PIN + error=1 + fi + else + warn "No 'oem_gpg_Admin_PIN=' statement found." + prompt_user_provisioning=1 + fi - echo "Mounting USB drive to provision OEM reownership from /media/oem-provisioning..." - /bin/mount-usb rw || warn "Unable to mount USB device. Continuing" - if [ -e /media/oem-provisioning ]; then - #TODO: trace mounted USB disk into /boot/oem - - oem_gpg_Admin_PIN=$(grep "^oem_gpg_Admin_PIN=" /media/oem-provisioning | cut -d "=" -f2) - oem_gpg_Admin_PIN_count=$(echo "$oem_gpg_Admin_PIN" | wc -l ) - if [ -n "$oem_gpg_Admin_PIN" ]; then - if [ $oem_gpg_Admin_PIN_count -eq 1 ]; then - export oem_gpg_Admin_PIN="$oem_gpg_Admin_PIN" - elif [ $oem_gpg_Admin_PIN_count -gt 1 ]; then - warn "Multiple 'oem_gpg_Admin_PIN=' statements found. None retained." - unset oem_gpg_Admin_PIN - error=1 + oem_gpg_User_PIN=$(grep "^oem_gpg_User_PIN=" /media/oem-provisioning | cut -d "=" -f2) + oem_gpg_User_PIN_count=$(echo "$oem_gpg_User_PIN" | wc -l ) + if [ -n "$oem_gpg_User_PIN" ]; then + if [ $oem_gpg_User_PIN_count -eq 1 ]; then + export oem_gpg_User_PIN="$oem_gpg_User_PIN" + elif [ $oem_gpg_User_PIN_count -gt 1 ]; then + warn "Multiple 'oem_gpg_Admin_PIN=' statements found. None retained." + unset oem_gpg_User_PIN + error=1 + fi + else + warn "No 'oem_gpg_User_PIN=' statement found." + prompt_user_provisioning=1 fi - else - warn "No 'oem_gpg_Admin_PIN=' statement found." - prompt_user_provisioning=1 - fi - oem_gpg_User_PIN=$(grep "^oem_gpg_User_PIN=" /media/oem-provisioning | cut -d "=" -f2) - oem_gpg_User_PIN_count=$(echo "$oem_gpg_User_PIN" | wc -l ) - if [ -n "$oem_gpg_User_PIN" ]; then - if [ $oem_gpg_User_PIN_count -eq 1 ]; then - export oem_gpg_User_PIN="$oem_gpg_User_PIN" - elif [ $oem_gpg_User_PIN_count -gt 1 ]; then - warn "Multiple 'oem_gpg_Admin_PIN=' statements found. None retained." - unset oem_gpg_User_PIN - error=1 + oem_gpg_real_name=$(grep "^oem_gpg_real_name=" /media/oem-provisioning | cut -d "=" -f2) + oem_gpg_real_name_count=$(echo "$oem_gpg_real_name" | wc -l ) + if [ -n "$oem_gpg_real_name" ]; then + if [ $oem_gpg_real_name_count -eq 1 ]; then + export oem_gpg_real_name="$oem_gpg_real_name" + elif [ $oem_gpg_real_name_count -gt 1 ]; then + warn "Multiple 'oem_gpg_real_name=' statements found. None retained." + unset oem_gpg_real_name + error=1 + fi + else + warn "No 'oem_gpg_real_name=' statement found." + prompt_user_provisioning=1 fi - else - warn "No 'oem_gpg_User_PIN=' statement found." - prompt_user_provisioning=1 - fi - oem_gpg_real_name=$(grep "^oem_gpg_real_name=" /media/oem-provisioning | cut -d "=" -f2) - oem_gpg_real_name_count=$(echo "$oem_gpg_real_name" | wc -l ) - if [ -n "$oem_gpg_real_name" ]; then - if [ $oem_gpg_real_name_count -eq 1 ]; then - export oem_gpg_real_name="$oem_gpg_real_name" - elif [ $oem_gpg_real_name_count -gt 1 ]; then - warn "Multiple 'oem_gpg_real_name=' statements found. None retained." - unset oem_gpg_real_name - error=1 + oem_gpg_email=$(grep "^oem_gpg_email=" /media/oem-provisioning | cut -d "=" -f2) + oem_gpg_email_count=$(echo "$oem_gpg_email" | wc -l ) + if [ -n "$oem_gpg_email" ]; then + if [ $oem_gpg_email_count -eq 1 ]; then + export oem_gpg_email="$oem_gpg_email" + elif [ $oem_gpg_email_count -gt 1 ]; then + warn "Multiple 'oem_gpg_email=' statements found. None retained." + unset oem_gpg_email + error=1 + fi + else + warn "No 'oem_gpg_email=' statement found." + prompt_user_provisioning=1 fi - else - warn "No 'oem_gpg_real_name=' statement found." - prompt_user_provisioning=1 - fi - oem_gpg_email=$(grep "^oem_gpg_email=" /media/oem-provisioning | cut -d "=" -f2) - oem_gpg_email_count=$(echo "$oem_gpg_email" | wc -l ) - if [ -n "$oem_gpg_email" ]; then - if [ $oem_gpg_email_count -eq 1 ]; then - export oem_gpg_email="$oem_gpg_email" - elif [ $oem_gpg_email_count -gt 1 ]; then - warn "Multiple 'oem_gpg_email=' statements found. None retained." - unset oem_gpg_email - error=1 + oem_gpg_comment=$(grep "^oem_gpg_comment=" /media/oem-provisioning | cut -d "=" -f2) + oem_gpg_comment_count=$(echo "$oem_gpg_comment" | wc -l ) + if [ -n "$oem_gpg_comment" ]; then + if [ $oem_gpg_comment_count -eq 1 ]; then + export oem_gpg_comment="$oem_gpg_comment" + elif [ $oem_gpg_comment -gt 1 ]; then + warn "Multiple 'oem_gpg_comment=' statements found. None retained." + unset oem_gpg_comment + error=1 + fi + else + warn "No 'oem_gpg_comment=' statement found." + prompt_user_provisioning=1 fi - else - warn "No 'oem_gpg_email=' statement found." - prompt_user_provisioning=1 - fi - oem_gpg_comment=$(grep "^oem_gpg_comment=" /media/oem-provisioning | cut -d "=" -f2) - oem_gpg_comment_count=$(echo "$oem_gpg_comment" | wc -l ) - if [ -n "$oem_gpg_comment" ]; then - if [ $oem_gpg_comment_count -eq 1 ]; then - export oem_gpg_comment="$oem_gpg_comment" - elif [ $oem_gpg_comment -gt 1 ]; then - warn "Multiple 'oem_gpg_comment=' statements found. None retained." - unset oem_gpg_comment - error=1 + oem_luks_actual_Disk_Recovery_Key=$(grep "^oem_luks_actual_Disk_Recovery_Key=" /media/oem-provisioning | cut -d "=" -f2) + oem_luks_actual_Disk_Recovery_Key_count=$(echo "$oem_luks_actual_Disk_Recovery_Key" | wc -l ) + if [ -n "$oem_luks_actual_Disk_Recovery_Key" ]; then + if [ $oem_luks_actual_Disk_Recovery_Key_count -eq 1 ]; then + export oem_luks_actual_Disk_Recovery_Key="$oem_luks_actual_Disk_Recovery_Key" + elif [ $oem_luks_actual_Disk_Recovery_Key_count -gt 1 ]; then + warn "Multiple 'oem_luks_actual_Disk_Recovery_Key=' statements found. None retained." + unset oem_luks_actual_Disk_Recovery_Key + error=1 + fi + else + warn "No 'oem_luks_actual_Disk_Recovery_Key=' statement found." + prompt_user_provisioning=1 fi - else - warn "No 'oem_gpg_comment=' statement found." - prompt_user_provisioning=1 - fi - oem_luks_actual_Disk_Recovery_Key=$(grep "^oem_luks_actual_Disk_Recovery_Key=" /media/oem-provisioning | cut -d "=" -f2) - oem_luks_actual_Disk_Recovery_Key_count=$(echo "$oem_luks_actual_Disk_Recovery_Key" | wc -l ) - if [ -n "$oem_luks_actual_Disk_Recovery_Key" ]; then - if [ $oem_luks_actual_Disk_Recovery_Key_count -eq 1 ]; then - export oem_luks_actual_Disk_Recovery_Key="$oem_luks_actual_Disk_Recovery_Key" - elif [ $oem_luks_actual_Disk_Recovery_Key_count -gt 1 ]; then - warn "Multiple 'oem_luks_actual_Disk_Recovery_Key=' statements found. None retained." - unset oem_luks_actual_Disk_Recovery_Key - error=1 + oem_luks_new_Disk_Recovery_Key=$(grep "^oem_luks_new_Disk_Recovery_Key=" /media/oem-provisioning | cut -d "=" -f2) + oem_luks_new_Disk_Recovery_Key_count=$(echo "$oem_luks_new_Disk_Recovery_Key" | wc -l ) + if [ -n "$oem_luks_new_Disk_Recovery_Key" ]; then + if [ $oem_luks_new_Disk_Recovery_Key_count -eq 1 ]; then + export oem_luks_new_Disk_Recovery_Key="$oem_luks_new_Disk_Recovery_Key" + elif [ $oem_luks_new_Disk_Recovery_Key_count -gt 1 ]; then + warn "Multiple 'oem_luks_new_Disk_Recovery_Key=' statements found. None retained." + unset oem_luks_new_Disk_Recovery_Key + error=1 + fi + else + warn "No 'oem_luks_new_Disk_Recovery_Key=' statement found." + prompt_user_provisioning=1 fi - else - warn "No 'oem_luks_actual_Disk_Recovery_Key=' statement found." - prompt_user_provisioning=1 - fi - oem_luks_new_Disk_Recovery_Key=$(grep "^oem_luks_new_Disk_Recovery_Key=" /media/oem-provisioning | cut -d "=" -f2) - oem_luks_new_Disk_Recovery_Key_count=$(echo "$oem_luks_new_Disk_Recovery_Key" | wc -l ) - if [ -n "$oem_luks_new_Disk_Recovery_Key" ]; then - if [ $oem_luks_new_Disk_Recovery_Key_count -eq 1 ]; then - export oem_luks_new_Disk_Recovery_Key="$oem_luks_new_Disk_Recovery_Key" - elif [ $oem_luks_new_Disk_Recovery_Key_count -gt 1 ]; then - warn "Multiple 'oem_luks_new_Disk_Recovery_Key=' statements found. None retained." - unset oem_luks_new_Disk_Recovery_Key - error=1 + oem_luks_Disk_Unlock_Key=$(grep "^oem_luks_Disk_Unlock_Key=" /media/oem-provisioning | cut -d "=" -f2) + oem_luks_Disk_Unlock_Key_count=$(echo "$oem_luks_Disk_Unlock_Key" | wc -l ) + if [ -n "$oem_luks_Disk_Unlock_Key" ]; then + if [ $oem_luks_Disk_Unlock_Key_count -eq 1 ]; then + export oem_luks_Disk_Unlock_Key="$oem_luks_Disk_Unlock_Key" + elif [ $oem_luks_Disk_Unlock_Key_count -gt 1 ]; then + warn "Multiple 'oem_luks_Disk_Unlock_Key=' statements found. None retained." + unset oem_luks_Disk_Unlock_Key + error=1 + fi + else + warn "No 'oem_luks_Disk_Unlock_Key=' statement found." + prompt_user_provisioning=1 fi - else - warn "No 'oem_luks_new_Disk_Recovery_Key=' statement found." - prompt_user_provisioning=1 - fi - oem_luks_Disk_Unlock_Key=$(grep "^oem_luks_Disk_Unlock_Key=" /media/oem-provisioning | cut -d "=" -f2) - oem_luks_Disk_Unlock_Key_count=$(echo "$oem_luks_Disk_Unlock_Key" | wc -l ) - if [ -n "$oem_luks_Disk_Unlock_Key" ]; then - if [ $oem_luks_Disk_Unlock_Key_count -eq 1 ]; then - export oem_luks_Disk_Unlock_Key="$oem_luks_Disk_Unlock_Key" - elif [ $oem_luks_Disk_Unlock_Key_count -gt 1 ]; then - warn "Multiple 'oem_luks_Disk_Unlock_Key=' statements found. None retained." - unset oem_luks_Disk_Unlock_Key - error=1 + oem_TPM_Owner_Password=$(grep "^oem_TPM_Owner_Password=" /media/oem-provisioning | cut -d "=" -f2) + oem_TPM_Owner_Password_count=$(echo "$oem_TPM_Owner_Password" | wc -l ) + if [ -n "$oem_TPM_Owner_Password" ]; then + if [ $oem_TPM_Owner_Password_count -eq 1 ]; then + export oem_TPM_Owner_Password="$oem_TPM_Owner_Password" + elif [ $oem_TPM_Owner_Password_count -gt 1 ]; then + warn "Multiple 'oem_TPM_Owner_Password=' statements found. None retained." + unset oem_TPM_Owner_Password + error=1 + fi + else + warn "No 'oem_TPM_Owner_Password=' statement found." + prompt_user_provisioning=1 fi - else - warn "No 'oem_luks_Disk_Unlock_Key=' statement found." - prompt_user_provisioning=1 - fi - oem_TPM_Owner_Password=$(grep "^oem_TPM_Owner_Password=" /media/oem-provisioning | cut -d "=" -f2) - oem_TPM_Owner_Password_count=$(echo "$oem_TPM_Owner_Password" | wc -l ) - if [ -n "$oem_TPM_Owner_Password" ]; then - if [ $oem_TPM_Owner_Password_count -eq 1 ]; then - export oem_TPM_Owner_Password="$oem_TPM_Owner_Password" - elif [ $oem_TPM_Owner_Password_count -gt 1 ]; then - warn "Multiple 'oem_TPM_Owner_Password=' statements found. None retained." - unset oem_TPM_Owner_Password - error=1 + if [ -n "$error" ] && [ "$error" -eq 1 ]; then + recovery "Please run 'vi /media/oem-provisioning' to correct previous warnings. ('i': insert, modify, 'Esc' key, then ':wq', 'Enter' key, then 'unmount /media' and 'reboot'." fi - else - warn "No 'oem_TPM_Owner_Password=' statement found." - prompt_user_provisioning=1 - fi - if [ -n $error ] && [ "$error" -eq 1 ]; then - recovery "Please run 'vi /media/oem-provisioning' to correct previous warnings. ('i': insert, modify, 'Esc' key, then ':wq', 'Enter' key, then 'unmount /media' and 'reboot'." - fi + if [ -n "$prompt_user_provisioning" ] && [ "$prompt_user_provisioning" -eq 1 ];then - if [ -n $prompt_user_provisioning ] && [ "$prompt_user_provisioning" -eq 1 ];then - #TODO prompt for provisioning of unfilled variables - #TODO: Put provisioning tracker into /boot/oem - #TODO: Put /media/provisioning provisioning partition tracker into /boot/oem - - for to_provision in oem_gpg_Admin_PIN oem_gpg_User_PIN oem_gpg_real_name oem_gpg_email oem_gpg_comment oem_luks_actual_Disk_Recovery_Key oem_luks_new_Disk_Recovery_Key oem_luks_Disk_Unlock_Key oem_TPM_Owner_Password - do - provisioned_value=$(eval echo \$$to_provision) - #debug "1-to_provision = $to_provision" - #debug "2-indirector = $provisioned_value" - - #count_str="_count" - #to_provision_count="$to_provision$count_str" - #to_provision_count_value=$(eval echo \$$to_provision_count) + #TODO: Put provisioning tracker into /boot/oem + #TODO: Put /media/provisioning provisioning partition tracker into /boot/oem - #We don't need that. We can check existence of $provisioned_value - #debug "3-to_provision_count = $to_provision_count" - #debug "4-to_provision_count_value= $to_provision_count_value" - - if [ -z "$provisioned_value" ];then - - echo "$to_provision is not set." - - if [ "$to_provision" == "oem_gpg_Admin_PIN" ] ;then - echo "We have limitations for Admin Pin: minimal 8 characters, no space." - echo "There is no need to have a super strong passphrase here, it will be locked after 3 bad attempts in the GPG smartcard." - echo "Suggested length: 2 random words diceware passphrase." - echo "Chosen GPG Admin PIN will be requested from you inside of Heads to seal HOTP firmware integrity measurements." - echo "Outside of Heads, your GPG User PIN will be prompted from you to sign/encrypt/authenticate with your GPG card." - passphrase=$(diceware-eff.sh 2 UpperFirstLetter Nospace) - #TODO:validate user choice - export oem_gpg_Admin_PIN=$passphrase - debug "oem_gpg_Admin_PIN=$oem_gpg_Admin_PIN" - fi - if [ "$to_provision" == "oem_gpg_User_PIN" ] ;then - echo "We have limitations for GPG Admin Pin: minimal 6 characters." - echo "There is no need to have a super strong passphrase here, it will be locked after 3 bad attempts in the GPG smartcard." - echo "Suggested length: 2 random words diceware passphrase." - echo "Chosen GPG User PIN will be requested from you from Heads each time a /boot configuration change is detected so you can validate it originated from you. From a QubesOS perspective, upgrading AdminVM (dom0) will most probably result in Heads requesting you to sign /boot integrity changes." - echo "Outside of Heads, the chosen GPG User PIN will be prompted from you to sign/encrypt/authenticate with your GPG card." - passphrase=$(diceware-eff.sh 2 UpperFirstLetter Nospace) - export oem_gpg_User_PIN=$passphrase - debug "oem_gpg_User_PIN=$oem_gpg_User_PIN" - fi - if [ "$to_provision" == "oem_luks_actual_Disk_Recovery_Key" ]; then - echo "The actual LUKS Recovery Key passphrase was provided to you from $oem_name." - echo "The actual LUKS Recovery Key passphrase is used to decrypt both USB and internal disk until reencrypted." - read -s -r -p "Please enter LUKS Recovery Key passphrase provided by $oem_name:" oem_luks_actual_Disk_Recovery_Key - #TODO: Validate that something was entered - echo - debug "oem_luks_actual_Disk_Recovery_Key=$oem_luks_actual_Disk_Recovery_Key" - #TODO: actual should be replaced by new LUKS recovery key after reencryption. - fi - if [ "$to_provision" == "oem_luks_new_Disk_Recovery_Key" ]; then - echo "Chosen new LUKS recovery Key passphrase needs to be remembered of you at all time." - echo "If forgotten, the content of both $oem_name shipped USB disk and computer internal disk will be lost forever." - echo "It is suggested that you choose a diceware passphrase of 6+ words." - #TODO replicate this with validation - password=$(diceware-eff.sh 7 UpperFirstLetter Nospace) - export oem_luks_new_Disk_Recovery_Key="$password" - debug "oem_luks_new_Disk_Recovery_Key=$oem_luks_new_Disk_Recovery_Key" - - fi - if [ "$to_provision" == "oem_luks_Disk_Unlock_Key" ] && [ "$CONFIG_TPM" == "y" ] && [ "$CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY" == "y" ]; then - echo "Chosen LUKS Disk Unlock Key will be requested at each boot until the next OS boot default." - echo "As opposed to the Disk Recovery Key passphrase, the Disk Unlock Key passphrase can be of a smaller length." - echo "A diceware randomly selected passphrase of 3 words is enough, considering that the TPM is rate limiting the attempts." - echo "Heads will prompt the user to boot with the Disk Recovery passphrase after 3 failed attempts on each reboot." - echo - echo "The Chosen LUKS Disk Unlock Key is an additional security measure of Heads, which permits disk decryption only if the firmware measurements valid." - echo "As a consequence, the Disk Unlock Key passphrase is bound to this computer and this computer only." - echo "As a result, someone cloning your disk and trying to decrypt its content by typing this passphrase will be unsuccessful." - echo "If forgotten, no problem. Select a new boot default and you will be prompted to enter chosen Disk Recovery Key Passphrase prior to defining a new Disk Unlock Key passphrase." - password=$(diceware-eff.sh 3 UpperFirstLetter Nospace) - export oem_luks_Disk_Unlock_Key="$password" - debug "oem_luks_Disk_Unlock_Key=$oem_luks_Disk_Unlock_Key" - fi - if [ "$to_provision" == "oem_TPM_Owner_Password" ] && [ "$CONFIG_TPM" == "y" ]; then - echo "Chosen TPM Owner Password will never be requested from Heads but in the reownership process to initialize it." - echo "A diceware randomly selected passphrase of 2 words is enough." - echo "It is recommended to reuse GPG Admin Passphrase/Password here, to not unecessarily multiply secrets to remember." - oem_TPM_Owner_Password="$oem_gpg_Admin_PIN" - #TODO: validate if ok with user, else generate - #password=$(diceware-eff.sh 2 UpperFirstLetter Nospace) - export oem_TPM_Owner_Password="$oem_TPM_Owner_Password" - debug "oem_TPM_Owner_Password=$oem_TPM_Owner_Password" - fi + if (whiptail $CONFIG_WARNING_BG_COLOR --title "OEM Reownership Wizard lacks some provisioning information" \ + --yesno "Would you like to feed the OEM Reownership Wizard once with all required\ninformation to automate its process?\n\n Those will be saved securely on OEM provided USB disk encrypted container.\n\n Provisioning those secrets here will automate Reownership Wizard process.\n Those information will be stored under /media/oem-provisioning.\n\nOtherwise, you will be prompted to enter them several times manually.\nYou won't either have an external backup of those information in case\nthey were forgotten.\n\nContinue with one time OEM Reownership information provisioning?" 30 90) then + #TODO: explain each option: n to generate diceware passwords until k, or m to show 500 to pick from, unvalidated. + #TODO: Put mounted partition in /boot/oem for automounting + for to_provision in oem_gpg_Admin_PIN oem_gpg_User_PIN oem_gpg_real_name oem_gpg_email oem_gpg_comment oem_luks_actual_Disk_Recovery_Key oem_luks_new_Disk_Recovery_Key oem_luks_Disk_Unlock_Key oem_TPM_Owner_Password + do + provisioned_value=$(eval echo \$$to_provision) + #debug "1-to_provision = $to_provision" + #debug "2-indirector = $provisioned_value" + + #count_str="_count" + #to_provision_count="$to_provision$count_str" + #to_provision_count_value=$(eval echo \$$to_provision_count) + + #We don't need that. We can check existence of $provisioned_value + #debug "3-to_provision_count = $to_provision_count" + #debug "4-to_provision_count_value= $to_provision_count_value" + + if [ -z "$provisioned_value" ];then + + echo "$to_provision is not set." + + if [ "$to_provision" == "oem_gpg_Admin_PIN" ]; then + clear + echo "$to_provision: GPG Admin PIN" + echo + echo "Here chosen GPG Admin PIN will be requested from you under Heads to visually attest integrity measurements on NitroKey/Librem Key (HOTP)." + echo "Outside of Heads, your GPG Admin PIN will be prompted from you to manage your Nitrokey/Librem Key. (e.g: Change user PIN.)" + echo "IMPORTANT: GPG Admin PIN is required to unlock GPG User PIN locked from 3 consecutive bad User PINs." + echo "If you mistyped your GPG Admin PIN 2 times in a subsequently, MAKE SURE YOUR THIRD ATTEMPT IS VALID by checking oem-provisioning file, created from this Wizard on OEM provided sdcard's encrypted container." + echo + echo "IMPORTANT: If the GPG Admin PIN becomes locked in smartcard THE CARD WILL NEED TO BE FACTORY RESETTED!" + echo "Factory reset of the GPG card deletes everything on it, including your private keys stored in its embedded GPG smartcard." + echo "Consequently, you won't be able to decrypt previous files and emails with your Nitrokey/Librem Key like prior to the reset." + echo + echo "There is no need to have a super strong passphrase here, it will be locked after 3 bad attempts in the GPG smartcard itself." + echo "Better choose a simple, short passphrase that you'll remember forever then one long that would lock yourself off because forgotten." + echo "Suggested passphrase length: 2 words diceware passphrase." + randomize_diceware_passphrases_until_chosen_or_manual 2 UpperFirstLetter Nospace + while [[ ${#passphrase} -lt 8 || ${#passphrase} -gt 20 ]] || [ "$passphrase" != "${passphrase% *}" ]; do + echo "We have limitations on Admin Pin: minimal 8 and maximal length of 20 characters, NO SPACE!" + validate_input_passphrases_are_equal + done + #TODO:validate user choice + export oem_gpg_Admin_PIN="$passphrase" + debug "oem_gpg_Admin_PIN=$oem_gpg_Admin_PIN" + fi + if [ "$to_provision" == "oem_gpg_User_PIN" ] ;then + clear + echo "$to_provision: GPG User PIN" + echo + echo "Chosen GPG User PIN will be requested from you from Heads each time a /boot configuration change is detected so you can sign it originated from you. From a QubesOS perspective, upgrading AdminVM (dom0) will most certainly result in Heads requesting you to sign /boot integrity changes." + echo "Outside of Heads, the chosen GPG User PIN will be prompted from you to sign/encrypt/authenticate with your GPG card." + echo + echo "There is no need to have a super strong passphrase here, it will be locked after 3 bad attempts in the GPG smartcard." + echo "Suggested length: 2 random words diceware passphrase." + randomize_diceware_passphrases_until_chosen_or_manual 2 UpperFirstLetter Nospace + while [[ ${#passphrase} -lt 6 || ${#passphrase} -gt 20 ]]; do + echo "We have limitations for GPG Admin Pin: minimal 6 and maximal length of 20 characters" + validate_input_passphrases_are_equal + done + export oem_gpg_User_PIN="$passphrase" + debug "oem_gpg_User_PIN=$oem_gpg_User_PIN" + fi + if [ "$to_provision" == "oem_gpg_real_name" ]; then + clear + echo "$to_provision: GPG public key associated Real Name" + echo + passphrase="" + while [[ ${#passphrase} -lt 5 || ${#passphrase} -gt 255 ]]; do + echo "We have limitations for GPG Real Name: minimal 5 and maximal length of 255 characters" + validate_input_passphrases_are_equal + done + export oem_gpg_real_name="$passphrase" + debug "oem_gpg_real_name=$oem_gpg_real_name" + fi + if [ "$to_provision" == "oem_gpg_email" ]; then + clear + echo "$to_provision: GPG public key associated primary E-Mail" + echo + passphrase="" + while ! $(expr "$passphrase" : '.*@' >/dev/null); do + echo "Please provide a valid GPG E-Mail format adress (name@domain), even if public key will not associated with any." + validate_input_passphrases_are_equal + done + export oem_gpg_email="$passphrase" + debug "oem_gpg_email=$oem_gpg_email" + fi + if [ "$to_provision" == "oem_gpg_comment" ]; then + clear + echo "$to_provision: GPG public key associated comment" + echo + echo "Differenciates usage of public keys that would be associated with same Real Name and E-Mails addresses if many. (e.g: for E-Mail correspondants)" + passphrase="" + while [[ ${#passphrase} -gt 60 ]] || [[ -z "$passphrase" ]]; do + echo "We have limitations for GPG public key associated comment: maximal length of 60 characters" + validate_input_passphrases_are_equal + done + export oem_gpg_comment="$passphrase" + debug "oem_gpg_comment=$oem_gpg_comment" + fi + if [ "$to_provision" == "oem_luks_actual_Disk_Recovery_Key" ]; then + clear + echo "$to_provision: actual Disk Recovery Key passphrase" + echo + echo "After disks reencryption, you'll have to enter your own, new Disk Recovery Key passphrase to unlock both OEM provided microsd card and insternal disks." + echo + echo "The actual LUKS Disk Recovery Key passphrase was provided to you from $oem_name. Type it here as provided." + echo "The actual LUKS Disk Recovery Key passphrase is used to decrypt both microsd and internal disks until reencrypted by this Wizard." + passphrase="" + while [[ -z "$passphrase" ]]; do + echo "Make sure that this corresponds to the Disk Recovery Key passphrase provided by $oem_name." + validate_input_passphrases_are_equal + done + export oem_luks_actual_Disk_Recovery_Key="$passphrase" + debug "oem_luks_actual_Disk_Recovery_Key=$oem_luks_actual_Disk_Recovery_Key" + #TODO: actual should be replaced by new LUKS recovery key after reencryption. + fi + if [ "$to_provision" == "oem_luks_new_Disk_Recovery_Key" ]; then + clear + echo "$to_provision: new Disk Recovery Key passphrase" + echo + echo "Chosen new LUKS recovery Key passphrase NEEDS TO BE REMEMBERED of you at all time!!!" + echo "LUKS Disk Recovery key Passphrase will be used to decrypt the content of your USB and computer disk content, from any computer." + echo + echo "If forgotten, the content of both $oem_name shipped microsd disk and computer internal disk will be lost forever." + echo "It is suggested that you pick a diceware passphrase of 6+ words. Make something emotionnaly involving from those words." + #TODO replicate this with validation + randomize_diceware_passphrases_until_chosen_or_manual 6 UpperFirstLetter Nospace + while [[ ${#passphrase} -lt 25 ]]; do + echo "We impose a minimal requirement of 25 characters for LUKS Disk Recovery Passphrase." + echo "Remember that a 5 words diceware passphrase would have took 165 days to break in 2013 for the NSA." + echo "A 6 words diceware passphrase would have took 3505 years. Choose carefully following your threat model." + echo "Your brain remembers anything that is emotionnaly bonding. Create a story that your brain will remember." + validate_input_passphrases_are_equal + done + export oem_luks_new_Disk_Recovery_Key="$passphrase" + debug "oem_luks_new_Disk_Recovery_Key=$oem_luks_new_Disk_Recovery_Key" + + fi + if [ "$to_provision" == "oem_luks_Disk_Unlock_Key" ] && [ "$CONFIG_TPM" == "y" ] && [ "$CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY" == "y" ]; then + clear + echo "$to_provision: Disk Unlock Key passphrase" + echo + echo "Chosen LUKS Disk Unlock Key passphrase will be requested at each boot until the a next OS boot default will be requested from OS upgrade." + echo "The LUKS Disk Unlock Key is an additional security measure of Heads which permits disk decryption only if the firmware measurements valid." + echo "As a consequence, the Disk Unlock Key passphrase is bound to this computer Trusted Platform Module (TPM) only." + echo "As a result, someone cloning your disk and trying to decrypt its content by typing this Disk Unlock Key passphrase will be unsuccessful." + echo "If forgotten, no problem. Select a new boot default and you will be prompted to enter chosen Disk Recovery Key Passphrase prior to defining a new Disk Unlock Key passphrase." + echo + echo "As opposed to the Disk Recovery Key passphrase, the Disk Unlock Key passphrase can be of a smaller length." + echo "A diceware randomly selected passphrase of 3 words is more then enough, considering that the TPM is rate limiting the attempts." + echo "Heads will force the user to boot with the Disk Recovery passphrase after 3 failed attempts on each reboot, making this password practically difficult to bruteforce." + echo + randomize_diceware_passphrases_until_chosen_or_manual 3 UpperFirstLetter Nospace + validate_input_passphrases_are_equal + export oem_luks_Disk_Unlock_Key="$passphrase" + debug "oem_luks_Disk_Unlock_Key=$oem_luks_Disk_Unlock_Key" + fi + if [ "$to_provision" == "oem_TPM_Owner_Password" ] && [ "$CONFIG_TPM" == "y" ]; then + clear + echo "$to_provision: TPM Owner Passphrase" + echo + echo "Chosen TPM Owner Passphrase will never be requested from Heads but in the reownership process to initialize it once." + echo "A diceware randomly selected passphrase of 2 words is enough." + echo "It is recommended to reuse GPG Admin Passphrase/Password here, to not unecessarily multiply secrets to remember." + echo "We reused the GPG Admin PIN to set the TPM Owner Passphrase." + oem_TPM_Owner_Password="$oem_gpg_Admin_PIN" + export oem_TPM_Owner_Password="$oem_TPM_Owner_Password" + debug "oem_TPM_Owner_Password=$oem_TPM_Owner_Password" + fi + else + echo "$to_provision is $provisioned_value." + fi + done + env|grep "oem_"|sort > /media/oem_provisioning + mount -o remount,ro /media else - echo "$to_provision is $provisioned_value." + echo "no_automatic_provisioning" >> /boot/oem + debug "no automatic provisioning" fi - done - recovery "this is where we would prompt user to provisidon once automatic provisioning of secrets in the EOM reownership Wizard." - - #Could be a for loop of all undefined variables? - #Do prompt of specifc constraints - #GPG Admin: no space. - #Admin PIN: >8 chars. User Pins > 6 chars - #GPG email format validation - #GPG Name > 5 char < 30 - #Validate double prompt validated input - #Store by appending to /media/oem-provisioning - fi + + recovery "this is where we would prompt user to provisidon once automatic provisioning of secrets in the EOM ReOwnership Wizard." + + #Could be a for loop of all undefined variables? + #Do prompt of specifc constraints + #GPG Admin: no space. + #Admin PIN: >8 chars. User Pins > 6 chars + #GPG email format validation + #GPG Name > 5 char < 30 + #Validate double prompt validated input + #Store by appending to /media/oem-provisioning + fi - export oem_configuration_read=1 - umount /media + export oem_configuration_read=1 + umount /media + fi fi } @@ -699,3 +802,65 @@ reset_disk_unlock_key() continue fi } +randomize_diceware_passphrases_until_chosen_or_manual() +{ + #We generate passwords folowing callers restriction until user chooses to keep it + keep=0 + unset keep_passphrase + + while [ "$keep" -eq 0 ] && [ "$keep" -eq 0 -a "$keep_passphrase" != "m" ]; do + echo "Generating passphrase..." + passphrase=$(diceware-eff.sh $1 $2 $3) + input_ok="n" + + while [ "$input_ok" != "y" ]; do + echo "Generated passphrase is: $passphrase" + read \ + -n 1 \ + -p "Keep this passphrase (k), generate a new one (n), or enter it manually [k/n/m]: " \ + keep_passphrase + echo + if [ "$keep_passphrase" = "k" ] || [ "$keep_passphrase" = "n" ] || [ "$keep_passphrase" = "m" ]; then + input_ok="y" + else + echo "invalid input. Valid choices were: k,n or m." + fi + done + + if [ "$keep_passphrase" = "k" ]; then + keep=1 + elif [ "$keep_passphrase" = "n" ]; then + randomize_diceware_passphrases_until_chosen_or_manual $1 $2 $3 + elif [ "$keep_passphrase" = "m" ]; then + unset passphrase + echo "It is suggested that you pick EFF diceware words to construct this passphrase." + echo "Shuffling EFF Diceware dictionary and sampling 500 words out of it..." + diceware-eff.sh 500 Capitalize + fi + done +} +validate_input_passphrases_are_equal() +{ + passphrase1="1" + passphrase2="2" + + while [ "$passphrase1" != "$passphrase2" ]; do + read \ + -p "Please type desired value: " \ + passphrase1 + echo + + read \ + -p "Please retype desired value: " \ + passphrase2 + echo + + if [ "$passphrase1" != "$passphrase2" ] || [ -z "$passphrase1" ]; then + echo "Entered value were different. Please type them again so they match." + else + passphrase="$passphrase1" + unset passphrase1 + unset passphrase2 + fi + done +} From 2e13cfc50dcae0646c515f8b6c36b12e38c06b33 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Tue, 28 May 2019 17:58:23 -0400 Subject: [PATCH 49/91] OEM: testing duplicate problems and attempts to launch vi dynamically, premodifying the file first. --- initrd/bin/gui-init | 2 +- initrd/etc/functions | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/initrd/bin/gui-init b/initrd/bin/gui-init index 0504d8c52..4d45a5d44 100755 --- a/initrd/bin/gui-init +++ b/initrd/bin/gui-init @@ -106,7 +106,7 @@ mount_boot if [ -e /boot/oem ];then if [ -z "$oem_configuration_read" ]; then #Read /media/oem-provisioning file once to read provisioned secrets - read_oem_file + read_oem_files fi fi diff --git a/initrd/etc/functions b/initrd/etc/functions index c4ef90ad5..ed9b7d87f 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -311,7 +311,7 @@ replace_config() { combine_configs() { cat /etc/config* > /tmp/config } -read_oem_file() +read_oem_files() { #TODO: check if /boot/oem contains past microsd disk and automount it. see tracing TODO below oem_name=$(grep "oem_name" /boot/oem | awk -F '=' {'print $2'}) @@ -325,10 +325,13 @@ read_oem_file() if ! [ $(grep "no_automatic_provisioning" /boot/oem) ]; then echo "Mounting USB drive to provision OEM reownership from /media/oem-provisioning..." - /bin/mount-usb rw || warn "Unable to mount USB device. Continuing" + /bin/mount-usb || warn "Unable to mount USB device. Continuing" #By default, OEM should provide oem-provisioning file with at least "oem_luks_actual_Disk_Recovery_Key" defined and reach this point. #If the user decides to not provision OEM through this file, that file will be deleted, and no_automatic_provisioning outputted in /boot/oem - + + #TODO: OEM PROVISIONING SHOULD HAPPEN ONLY OVER ENCRYPTED PARTITION. + # FILES CANNOT BE DELETED ON FLASH (BE IT SSD OR SD DEVICES APPLYING WEAR LEVELING) + #ICI valider mount point if [ -e /media/oem-provisioning ]; then #TODO: trace mounted USB disk into /boot/oem @@ -469,7 +472,12 @@ read_oem_file() fi if [ -n "$error" ] && [ "$error" -eq 1 ]; then - recovery "Please run 'vi /media/oem-provisioning' to correct previous warnings. ('i': insert, modify, 'Esc' key, then ':wq', 'Enter' key, then 'unmount /media' and 'reboot'." + mount -o remount,rw /media + #sed -i '1s;^;#This is vi Editor. To edit this file, press "i" to enter Insert mode.\n#Then edit as you want\n#When done, press the "Esc" escape key\n#Then type ":wq" and press 'Enter' key.\n' /media/oem-provisioning + awk '{print "#This is vi Editor. To edit this file, press 'i' to enter Insert mode.\n#Then edit as you want\n#When done, pres 'Esc' escape key\n#Then type ':wq' and press 'Enter' key to save and exit.\n" $0}' file + vi /media/oem-provisioning + mount -o remount,ro /media + reboot fi if [ -n "$prompt_user_provisioning" ] && [ "$prompt_user_provisioning" -eq 1 ];then @@ -660,7 +668,7 @@ read_oem_file() fi - recovery "this is where we would prompt user to provisidon once automatic provisioning of secrets in the EOM ReOwnership Wizard." + #recovery "this is where we would prompt user to provisidon once automatic provisioning of secrets in the EOM ReOwnership Wizard." #Could be a for loop of all undefined variables? #Do prompt of specifc constraints From bb2a9d35d180b65ef08e51f6adce4e47ff636a70 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Mon, 3 Jun 2019 21:21:50 -0400 Subject: [PATCH 50/91] x230: add mmc and sdhci support. note: mount-usb is modified to only mount /media if not mounted so other scripts can work with calling mount-sdcard instead of mount-usb --- boards/x230/x230.config | 1 + config/linux-x230.config | 3 +++ 2 files changed, 4 insertions(+) diff --git a/boards/x230/x230.config b/boards/x230/x230.config index d2f8a8aee..a2c993af1 100644 --- a/boards/x230/x230.config +++ b/boards/x230/x230.config @@ -25,6 +25,7 @@ CONFIG_LIBREMKEY=y CONFIG_LINUX_USB=y CONFIG_LINUX_E1000E=y +export CONFIG_LINUX_SDHCI=y export CONFIG_TPM=y export CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY=y diff --git a/config/linux-x230.config b/config/linux-x230.config index 2e6a9617f..bc8544c07 100644 --- a/config/linux-x230.config +++ b/config/linux-x230.config @@ -192,6 +192,9 @@ CONFIG_USB_XHCI_PLATFORM=m CONFIG_USB_EHCI_HCD=m CONFIG_USB_EHCI_HCD_PLATFORM=m CONFIG_USB_STORAGE=m +CONFIG_MMC=m +CONFIG_MMC_SDHCI=m +CONFIG_MMC_SDHCI_PCI=m CONFIG_RTC_CLASS=y # CONFIG_X86_PLATFORM_DEVICES is not set CONFIG_INTEL_IOMMU=y From 1258e294a88cd5e2b8052ee0070c5fe42930d0dd Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Mon, 3 Jun 2019 21:23:05 -0400 Subject: [PATCH 51/91] OEM reownership: force to be on AC Power, else poweroff. --- initrd/bin/gui-init | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/initrd/bin/gui-init b/initrd/bin/gui-init index 4d45a5d44..4072ced68 100755 --- a/initrd/bin/gui-init +++ b/initrd/bin/gui-init @@ -105,8 +105,15 @@ update_totp() mount_boot if [ -e /boot/oem ];then if [ -z "$oem_configuration_read" ]; then - #Read /media/oem-provisioning file once to read provisioned secrets - read_oem_files + #make sure the system is powered by AC outlet + if [ $(cat /sys/class/power_supply/AC/online) -eq 1 ]; then + #Read /media/oem-provisioning file once to read provisioned secrets + read_oem_files + else + clear + notify "You must run the Reownership Wizard from a safe place with power outlet connected. OWM Reownership will require around an hour. Sytem will now power off." + poweroff + fi fi fi From 11e66daba4dad6ef4e1f3b45204e21c15dbec2ea Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Mon, 3 Jun 2019 21:24:20 -0400 Subject: [PATCH 52/91] mount-usb: removed legacy support for board config defined USB device. TODO: I still think a mount-external would be nice, or a script detecting devices changes after a prompt. The user still needs to know device/partition hierarchy. And OEMs need to mount /dev/sdb1 manually from dockstation for reimaging. --- initrd/bin/mount-usb | 8 -------- 1 file changed, 8 deletions(-) diff --git a/initrd/bin/mount-usb b/initrd/bin/mount-usb index 6c26bccf0..b059fdc36 100755 --- a/initrd/bin/mount-usb +++ b/initrd/bin/mount-usb @@ -38,10 +38,6 @@ fi #Only mount /media device if not mounted. Calling scripts are responsible to unmount when done if another script might need a different USB drive. if ! grep -q /media /proc/mounts ; then stat -c %N /sys/block/sd* | grep usb | cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" > /tmp/usb_block_devices - #In case CONFIG_USB_BOOT_DEV was just a secondary device specified in board configuration and found, add it to the list - stat -c %N $CONFIG_USB_BOOT_DEV | grep -v usb| cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" >> /tmp/usb_block_devices - devices=$(cat /tmp/usb_block_devices |uniq|sort) - echo "$devices" > /tmp/usb_block_devices if [ -z `cat /tmp/usb_block_devices` ]; then if [ -x /bin/whiptail ]; then whiptail --title 'USB Drive Missing' \ @@ -52,10 +48,6 @@ if ! grep -q /media /proc/mounts ; then fi sleep 1 stat -c %N /sys/block/sd* | grep usb | cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" > /tmp/usb_block_devices - #In case CONFIG_USB_BOOT_DEV was just a secondary device specified in board configuration and found, add it to the list - stat -c %N $CONFIG_USB_BOOT_DEV | grep -v usb| cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" >> /tmp/usb_block_devices - devices=$(cat /tmp/usb_block_devices |uniq|sort) - echo "$devices" > /tmp/usb_block_devices if [ -z `cat /tmp/usb_block_devices` ]; then if [ -x /bin/whiptail ]; then whiptail $CONFIG_ERROR_BG_COLOR --title 'ERROR: USB Drive Missing' \ From feb5b4d05b00d65ce59148a34ad0e9a640832d04 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Mon, 3 Jun 2019 21:27:28 -0400 Subject: [PATCH 53/91] functions: enable_sdcard: copy cat of mount-usb for mmc/sdcard in memory card extension bay (really useful for OEM. No need to ship USB adapter.) notify: addition to diplay message and requiring user input read_oem_files: now depends on sdcard, on which a LUKS partition is provided. randomize_diceware_passphrases_until_chosen_or_manual: manual now ouputs 1000 shuffled EFF dictionary words to select from for manual passphrase selection. --- initrd/etc/functions | 96 +++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 51 deletions(-) diff --git a/initrd/etc/functions b/initrd/etc/functions index ed9b7d87f..9d9863df2 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -12,6 +12,11 @@ debug(){ read -p 'Hit enter to continue.' } +notify(){ + echo >&2 "$*"; + read -p 'Hit enter to continue.' +} + error() { echo >&2 "$*"; exit 1; @@ -94,6 +99,28 @@ confirm_totp() echo } +enable_sdcard() +{ + if [ "$CONFIG_LINUX_SDHCI" = "y" ]; then + if ! lsmod | grep -q mmc_core; then + insmod /lib/modules/mmc_core.ko \ + || die "mmc_core: module load failed" + fi + if ! lsmod | grep -q mmc_block; then + insmod /lib/modules/mmc_block.ko \ + || die "mmc_block: module load failed" + fi + if ! lsmod | grep -q sdhci; then + insmod /lib/modules/sdhci.ko \ + || die "sdhci: module load failed" + fi + if ! lsmod | grep -q sdhci_pci; then + insmod /lib/modules/sdhci-pci.ko \ + || die "sdhci-pci: module load failed" + fi + fi +} + enable_usb() { if [ "$CONFIG_LINUX_USB_COMPANION_CONTROLLER" = y ]; then @@ -321,20 +348,11 @@ read_oem_files() oem_name="your OEM" export oem_name="$oem_name" fi - + if ! [ $(grep "no_automatic_provisioning" /boot/oem) ]; then - - echo "Mounting USB drive to provision OEM reownership from /media/oem-provisioning..." - /bin/mount-usb || warn "Unable to mount USB device. Continuing" - #By default, OEM should provide oem-provisioning file with at least "oem_luks_actual_Disk_Recovery_Key" defined and reach this point. - #If the user decides to not provision OEM through this file, that file will be deleted, and no_automatic_provisioning outputted in /boot/oem - - #TODO: OEM PROVISIONING SHOULD HAPPEN ONLY OVER ENCRYPTED PARTITION. - # FILES CANNOT BE DELETED ON FLASH (BE IT SSD OR SD DEVICES APPLYING WEAR LEVELING) - - #ICI valider mount point + echo "Mounting memory card reader drive provision OEM reownership from /media/oem-provisioning..." + /bin/mount-sdcard || recovery "Unable to mount sdcard from memory card reader. Make sure the card is pushed in and type 'reboot' to continue." if [ -e /media/oem-provisioning ]; then - #TODO: trace mounted USB disk into /boot/oem echo "Found /media/oem-provisioning. Parsing..." oem_gpg_Admin_PIN=$(grep "^oem_gpg_Admin_PIN=" /media/oem-provisioning | cut -d "=" -f2) oem_gpg_Admin_PIN_count=$(echo "$oem_gpg_Admin_PIN" | wc -l ) @@ -472,41 +490,26 @@ read_oem_files() fi if [ -n "$error" ] && [ "$error" -eq 1 ]; then + notify "Please take note of precedent errors detected in /media/oem-provisioning content." mount -o remount,rw /media - #sed -i '1s;^;#This is vi Editor. To edit this file, press "i" to enter Insert mode.\n#Then edit as you want\n#When done, press the "Esc" escape key\n#Then type ":wq" and press 'Enter' key.\n' /media/oem-provisioning - awk '{print "#This is vi Editor. To edit this file, press 'i' to enter Insert mode.\n#Then edit as you want\n#When done, pres 'Esc' escape key\n#Then type ':wq' and press 'Enter' key to save and exit.\n" $0}' file + sed -i '/^#/d' /media/oem-provisioning + sed -i '1i #This is vi Editor.\n#\n#Please delete duplicate values to be fed to the OEM Rownership Wizard.\n#To edit this file, press "i" to enter Insert mode.\n#Delete duplicates and undesired values.\n#Required format is: "to_be_provided_value=value"\n#\n#When done, press the "Esc" escape key\n#Then type ":wq" and press the 'Enter' key.\n#The wizard will then validate you input for length requirements only.\n#\n#\n#' /media/oem-provisioning vi /media/oem-provisioning + sed -i '/^#/d' /media/oem-provisioning mount -o remount,ro /media - reboot + unset error + read_oem_files fi if [ -n "$prompt_user_provisioning" ] && [ "$prompt_user_provisioning" -eq 1 ];then - #TODO: Put provisioning tracker into /boot/oem - #TODO: Put /media/provisioning provisioning partition tracker into /boot/oem - if (whiptail $CONFIG_WARNING_BG_COLOR --title "OEM Reownership Wizard lacks some provisioning information" \ --yesno "Would you like to feed the OEM Reownership Wizard once with all required\ninformation to automate its process?\n\n Those will be saved securely on OEM provided USB disk encrypted container.\n\n Provisioning those secrets here will automate Reownership Wizard process.\n Those information will be stored under /media/oem-provisioning.\n\nOtherwise, you will be prompted to enter them several times manually.\nYou won't either have an external backup of those information in case\nthey were forgotten.\n\nContinue with one time OEM Reownership information provisioning?" 30 90) then - #TODO: explain each option: n to generate diceware passwords until k, or m to show 500 to pick from, unvalidated. - #TODO: Put mounted partition in /boot/oem for automounting for to_provision in oem_gpg_Admin_PIN oem_gpg_User_PIN oem_gpg_real_name oem_gpg_email oem_gpg_comment oem_luks_actual_Disk_Recovery_Key oem_luks_new_Disk_Recovery_Key oem_luks_Disk_Unlock_Key oem_TPM_Owner_Password do provisioned_value=$(eval echo \$$to_provision) - #debug "1-to_provision = $to_provision" - #debug "2-indirector = $provisioned_value" - - #count_str="_count" - #to_provision_count="$to_provision$count_str" - #to_provision_count_value=$(eval echo \$$to_provision_count) - - #We don't need that. We can check existence of $provisioned_value - #debug "3-to_provision_count = $to_provision_count" - #debug "4-to_provision_count_value= $to_provision_count_value" - if [ -z "$provisioned_value" ];then - echo "$to_provision is not set." - if [ "$to_provision" == "oem_gpg_Admin_PIN" ]; then clear echo "$to_provision: GPG Admin PIN" @@ -528,7 +531,6 @@ read_oem_files() echo "We have limitations on Admin Pin: minimal 8 and maximal length of 20 characters, NO SPACE!" validate_input_passphrases_are_equal done - #TODO:validate user choice export oem_gpg_Admin_PIN="$passphrase" debug "oem_gpg_Admin_PIN=$oem_gpg_Admin_PIN" fi @@ -660,28 +662,20 @@ read_oem_files() echo "$to_provision is $provisioned_value." fi done - env|grep "oem_"|sort > /media/oem_provisioning + + mount -o remount,rw /media + env|grep "oem_" | sort > /media/oem_provisioning mount -o remount,ro /media + else + mount -o remount,rw /boot echo "no_automatic_provisioning" >> /boot/oem + mount -o remount,ro /boot debug "no automatic provisioning" fi - - - #recovery "this is where we would prompt user to provisidon once automatic provisioning of secrets in the EOM ReOwnership Wizard." - - #Could be a for loop of all undefined variables? - #Do prompt of specifc constraints - #GPG Admin: no space. - #Admin PIN: >8 chars. User Pins > 6 chars - #GPG email format validation - #GPG Name > 5 char < 30 - #Validate double prompt validated input - #Store by appending to /media/oem-provisioning fi - export oem_configuration_read=1 - umount /media + mount -o remount,ro /media fi fi } @@ -842,8 +836,8 @@ randomize_diceware_passphrases_until_chosen_or_manual() elif [ "$keep_passphrase" = "m" ]; then unset passphrase echo "It is suggested that you pick EFF diceware words to construct this passphrase." - echo "Shuffling EFF Diceware dictionary and sampling 500 words out of it..." - diceware-eff.sh 500 Capitalize + echo "Shuffling EFF Diceware dictionary and sampling 1000 words out of it..." + diceware-eff.sh 1000 Capitalize fi done } From 9c357a5ca491a0fe1457b105423f6e91afc27e0f Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Mon, 3 Jun 2019 21:33:34 -0400 Subject: [PATCH 54/91] initrd/media/oem-provisioning: was not supposed to be here. --- initrd/media/oem-provisioning | 198 ---------------------------------- 1 file changed, 198 deletions(-) delete mode 100644 initrd/media/oem-provisioning diff --git a/initrd/media/oem-provisioning b/initrd/media/oem-provisioning deleted file mode 100644 index 459457cd6..000000000 --- a/initrd/media/oem-provisioning +++ /dev/null @@ -1,198 +0,0 @@ -########### -# OEM # -########### -# To activate OEM reownership wizard, under Heads recovery console, do: -# mount /boot -# mount -o remount,rw /boot -# echo "oem_name=COMPANY NAME" > /boot/oem -# mount -o remount,ro /boot -# reboot -# -# To activate OEM automatic provisioning, the content of this file needs to be found by Heads under: -# /media/oem-provisioning -# By default, the USB drive is mounted from /dev/sdb1 but "mount-usb" will find the usb drive and mount it under /media -# -# Replace variables content with your own! -# -#The following needs to be put in /boot/oem for OEM name to be shown at OEM Reownership wizard first screen. Else it is going to be "your OEM". -#oem_name=Insurgo Open Technologies -# -#On a recovery shell, type the UP arrow key until you reach top of the history buffer. A command is proposed for you to change "YOUR COMPANY" -# to your own. The hardware is then ready to ship and the wizard will accompany the user in reowning the hardware and OEM secrets on next reboot. -# -# You should invite the user into using "generate_diceware-eom-provisioning.sh" script in the current directory, -# which uses diceware to prefeed "oem-provisioning.generated" with proper secrets. -# The user would then need to put that file under "oem-provisioning" on the root of a dedicated USB drive and connect on first boot of -# received hardware to reduce user errors and friction of having to enter those secrets manually. - -######### -# GPG # -######### -# GPG card function in Heads: -# The Librem Key/NitroKey is a traditional GPG card added with HMAC-based One-time Password (HOTP) which permits -# to seal integrity measurements into the GPG card memory. -# -# As a functional result, at each boot, the card will flash its LED green if the measured boot integrity -# is atttested or red in case of a mismatch. This provable security measure is called tamper-evidence and -# informs the user that the Firmware (BIOS chips content) has been tampered with, or modified, and doesn't -# match expected measurements expected by the Trusted Platform Module (TPM) and validated by the GPG card. -# -# Heads traditionally stores Trusted Module Platform (TPM) Time-based One-time Password (TOTP) code in a -# smartphone through the scanning of a QR code into an OTP authenticator application when the TPM is reowned or -# when a firmware update is applied. Through the reownership process, the firmware will be modified by inserting -# public PGP key into the firmware, which will invalidate measurements and require the TOTP/HOTP to be resealed. -# The TPM itself will be reowned by the user, requesting him to set a passphrase. -# -# *** You should use both TOTP/HOTP so you can still validate attested integiryt in case your GPG card gets lost *** -# -# HOTP/TOTP are functionally similar, while the Librem Key/Nitrokey permits to validate integrity visually in an -# instant without having to unlock the smartphone, open the OTP application and verify that a 6 digits code there -# is the same that is shown on the screen. -# HOTP Librem Key/Nitrokey feature is complementory to the TOTP and shares the same codebase. -# -# Heads also depends on the GPG card to store used private key outside of prying eyes, securely stored on the -# Smartcard. When factory resetting the card, only the public key is inserted into the rom, which is used -# to automatically validate the integiryt of /boot files through checksuming and validating the the result -# matches what is signed with the private key on the GPG card. -# -# Heads will warn the user each time boot configuration changes. -# That will happen when the Operating System applies core system updates (Xen, Kernel, initrd (drivers) -# and grub configuration) while notifying the user of any addition/supression of files expected to be found -# in the /boot partition. -# -# GPG usage in Heads: -# Heads will prompt the user for: -# User PIN: -# Sign boot configuration changes. -# Admin PIN: -# Seal Firmware changes through HOTP -# -# IMPORTANT: -# The user should always reboot the system and sign configuration changes as soon as possible after system upgrades -# to attest the responsibility and ownership of the changes. -# -# The user should always be cautious about TOTP/HOTP errors if he didn't update the firmware himself. -# -# Heads primary goal is to attest of the integrity of the firmware and /boot files. -# That integrity attestation is based on those two practices that REQUIRES TO BE FOLLOWED. -# -# PIN Notes: GPG PINs are protected in the SmartCard. After 3 bad attempts, the SmartCard locks that account. -# When the User PIN is locked, the Admin PIN can be used to unlock User PIN. -# When the Admin PIN is locked, a Reset Code can be used to unlock Admin PIN. -# This is not provisioned by default. You will have to set one manually yourself. -# -# You can define an additional "Reset Code" to reset the Admin PIN manually by doing: -# gpg --card-edit -# admin -# passwd -# 4 - set the Reset Code -# Type Admin PIN -# -#GPG SmartCard desired Admin PIN to provision GPG factory reset. -# Admin PIN manages Admin functions of the card through gpg --edit-card admin functions, -# In Heads, the Admin PIN is required to seal HOTP secret into NitroKey/Librem Key when firmware has been modified. -# -# NOTES: If the GPG card is lost, the user won't be able to seal firmware changes through HOTP. -# Size constaints: minimum 8 characters, maximum 20 characters, WITHOUT SPACES! -# (Else HOTP cannot be sealed. It's a seal-libremkey limitation) -# No need to go crazy here. Remember that 3 bad attempts locks the account. One or two Diceware words are enough. -# Use KeepassXC password manager or something like https://www.rempe.us/diceware/#eff -oem_gpg_Admin_PIN=InsurgoTech -# -#GPG SmartCard desired User PIN to provision GPG factory reset. -# User PIN manages user functions of the card. It is used to encrypt files and e-mails, sign files and e-mails -# and authenticate the user in daily operations when used in combination with the public key generated. -# That public key needs to be kept, as it is impossible to export it from the smartcard. -# In Heads, the User PIN is required to sign boot configuration changes. -# At each boot, the imported public key counterpart is used to validate the checksums of the files signed with the card. -# -# NOTES: If the GPG card is lost, the user won't be able to sign system changes. -# Size constaints: minimum 6 characters, maximum 20 characters -# No need to go crazy here. Remember that 3 bad attempts locks the account. One or two Diceware words are enough. -# Use KeepassXC password manager or something like https://www.rempe.us/diceware/#eff -oem_gpg_User_PIN=Insurgo -#GPG SmartCard desired Real Name to provision GPG factory reset. -# This will be used to construct the ID of the public key: "Real Name (Comment) email@address.org" -# -# Size constaints: minimum 5 characters. -oem_gpg_real_name=Insurgo Integrity Delivered Attestation Attestation Librem Key -#GPG SmartCard desired E-mail address to provision GPG factory reset. -# This will be used to construct the ID of the public key: "Real Name (Comment) email@address.org" -# Note that some services requires that e-mail address to be real and will send an e-mail to validate it. -# If you intend to use the GPG card to encrypt/sign e-mails, this is a good idea to provide main e-mail account here. -oem_gpg_email=insurgo@riseup.net -#GPG SmartCard desired Comment to provision GPG factory reset. -# This will be used to construct the ID of the public key: "Real Name (Comment) email@address.org" -# If you have multiple cards associated with the same E-mail address, this is a good place to name it's usage difference -oem_gpg_comment=FACTORY RESET ME - -########## -# LUKS # -########## -# LUKS containers are used in Linux to encrypt whole filesystems. -# The whole idea behind OEM reownership depends on the LUKS reencryption of the container from the user when hardware -# is received. Otherwise, the OEM would know the cloned image LUKS Disk Recovery Key and could hand it to authorities. -# This provisioning wizard starts by asking you to enter the actual LUKS Disk Recovery Key passphrase to reencrypt the -# container completely, before changing it's passphrase with user selected one. -# -# This LUKS Disk Recovery Key, if provided by the OEM **** SHOULD NOT BE MODIFIED ***** -oem_luks_actual_Disk_Recovery_Key=InsurgoTech -# This is where you want to define your new Disk Recovery Key passphrase, which will be associated to the reencrypted LUKS -# container after the OEM wizard is over and become the Disk Recovery Key passphrase. -# -# This provisioning wizard continues by asking you to enter the desired LUKS Disk Recovery Key passphrase and changes -# it. -# -# The Disk Recovery Key will be prompted to the user in the following cases: -# 1-Every boot if no Disk Unlock Key was added to the TPM (NOT RECOMMENDED! could be captured and used on cloned disk) -# 2-If the TPM fails (Hardware failure) -# 3-If the firmware has been tampered with/upgraded/modified by the user -# -# NOTES: If the Disk Recovery Key Passphrase is lost, the user won't be able to set a new Disk Unlock Key. -# More importantly, in the case of a Operating System core update (Xen, Kernel, initrd (drivers) or grub config, -# the Default Boot option will be invalidated, and the only way to boot the system will be by typing this -# Disk Recovery Key Passphrase. ********** CHOOSE IT CAREFULLY SO YOU CAN EASILY REMEMBER IT *********** -# -# Size constaints: select a Diceware passphrase of at least 3 words. 6 is better. -# No need to go crazy here. It's better to have a shorter but strong passphrase you remember and not type often -# then a strong passphrase that locks you out of the system and requires you to reinstall. -# Use KeepassXC password manager or something alike https://www.rempe.us/diceware/#eff -oem_luks_new_Disk_Recovery_Key=InsurgoTech -# Disk Unlock Key Passphrase is the passphrase the user will be required to type under Heads to start the system. -# -# The Disk Unlock Key is another security feature enforced by Heads that makes your computer more trustworthy. -# The Disk Unlock Key is released by the Trusted Platform Module (TPM), a cryptographic component on which -# depends Heads to measure and attest firmware integrity, and released only if the measurements of the firmware -# are intact (sealed). In the case the firmware has been modified, that the user lost/forgot his GPG card, -# the Disk Unlock key passphrase will refuse to release the actual Disk Unlock Key and will not boot, unless -# you to type the Disk Recovery Key passphrase. -# -# Heads would not be able to unseal neither TOTP/HOTP in case measurements mismatche and will warn the user. -# -# The Disk Unlock Key passphrase will also not be able to unlock the disk if the LUKS header is not -# consistent with what was sealed into the TPM when selecting a default boot option. -# -# Functionnaly, selecting a default boot option and setting a Disk Unlock Key is a good security measure against -# prying eyes, let them be camera recording or over the shoulder passphrase capture. -# Since that Key is bounded with firmware integrity measurements from the TPM, that passphrase is bound to this -# computer only. -# -# A third party which would clone the disk and attempt to access its content later would succeed only if -# Disk Recovery Key passphrase was typed, not the Disk Unlock Key passphrase. -# -# Size constaints: Best is to select a Diceware passphrase of at least 4 words. 6+ is better. -# Use KeypassXC password manager or something like https://www.rempe.us/diceware/#eff -# No need to go crazy here. An attacker would have 3 attempts at a time when booting Heads. -# Use KeepassXC password manager or something like https://www.rempe.us/diceware/#eff -# You will be prompted to change this passphrase at every core Operating System upgrades since the default boot -# option will be modified. -oem_luks_Disk_Unlock_Key=Insurgo - -################################### -# Trusted Platform Module (TPM) # -################################### -# The TPM passphrase is required when sealing the Disk Unlock Key when selecting a new default boot option, -# combined with the GPG User PIN. -# -# It is recommended to reuse GPG Admin Passphrase/Password here, to not unecessarily multiply secrets to remember. -#oem_TPM_Owner_Password=InsurgoTech From 4a5a718854478d30a277dc4abc17e527411fa68f Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Mon, 3 Jun 2019 21:35:15 -0400 Subject: [PATCH 55/91] modules/linux: addition of mmc and sdhci dependencies if CONFIG_LINUX_SDHCI is defined in board config. --- modules/linux | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/linux b/modules/linux index f8817935b..2b8587d83 100644 --- a/modules/linux +++ b/modules/linux @@ -95,6 +95,12 @@ linux_modules-$(CONFIG_LINUX_NVME) += drivers/nvme/host/nvme-core.ko linux_modules-$(CONFIG_LINUX_MEI) += drivers/misc/mei/mei.ko linux_modules-$(CONFIG_LINUX_MEI) += drivers/misc/mei/mei-me.ko +# MMC/sdard support through Secure Digital Host Controller Interface support +linux_modules-$(CONFIG_LINUX_SDHCI) += drivers/mmc/core/mmc_core.ko +linux_modules-$(CONFIG_LINUX_SDHCI) += drivers/mmc/core/mmc_block.ko +linux_modules-$(CONFIG_LINUX_SDHCI) += drivers/mmc/host/sdhci.ko +linux_modules-$(CONFIG_LINUX_SDHCI) += drivers/mmc/host/sdhci-pci.ko + EXTRA_FLAGS := -fdebug-prefix-map=$(pwd)=heads -gno-record-gcc-switches linux_target := \ From fd9b145bc10ec4f46c7a2df8190de009b12fa118 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Mon, 3 Jun 2019 21:36:13 -0400 Subject: [PATCH 56/91] mount-sdcard: copy cat of mount-usb for sdhci/mmc cards. Useful for OEM provisioning --- initrd/bin/mount-sdcard | 140 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100755 initrd/bin/mount-sdcard diff --git a/initrd/bin/mount-sdcard b/initrd/bin/mount-sdcard new file mode 100755 index 000000000..586c280a1 --- /dev/null +++ b/initrd/bin/mount-sdcard @@ -0,0 +1,140 @@ +#!/bin/sh +# Mount a SDCARD device +. /etc/functions + +is_Luks_luksOpen() +{ + cryptsetup isLuks $SDCARD_MOUNT_DEVICE + if [ $(echo $?) == 0 ]; then + echo -e "\n\nSDCARD Device $SDCARD_MOUNT_DEVICE is encrypted.\nPlease type $oem_name provided Disk Recovery Key passphrase at next prompt.\n" + cryptsetup luksOpen $SDCARD_MOUNT_DEVICE sdcarddev + if [ $(echo $?) == 0 ] && [ $(grep -q oem_provisioning_partition /boot/oem) ]; then + mount -o remount,rw /boot + echo "oem_provisioning_partition=$SDCARD_MOUNT_DEVICE" >> /boot/oem + mount -o remount,ro /boot + fi + SDCARD_MOUNT_DEVICE="/dev/mapper/sdcarddev" + else + clear + notify "OEM Reownership Wizard only supports provisioning to/from a LUKS encrypted partition. Please prepare such sdcard and try again. System will now power off." + poweroff + fi + +} + +#OEM reownership, when attempting to load /media/oem-provisioning, +#requires mmc and sdhci related module to be inserted through enable_sdcard. +#which would normally modify PCR 5 through /sbin/insmod script. +# +#We bypass those measurements here by calling busybox's insmod directly, +#keeping PCR5 intact so that calling kexec-seal-key (to add Disk Unlock Key) +#in OEM mode gives the same measurements then when calling kexec-unseal-key +#in normal boot mode after OEM reownership. +if [ -e /boot/oem ]; then + alias insmod='busybox insmod' + SDCARD_MOUNT_DEVICE=$(grep "^oem_provisioning_partition=" /boot/oem | cut -d "=" -f2) +fi + +enable_sdcard +sleep 1 + +if [ ! -d /media ]; then + mkdir /media +fi + +#Only mount /media device if not mounted. Calling scripts are responsible to unmount when done if another script might need a different SDCARD drive. +if ! grep -q /media /proc/mounts ; then + if [ -z "$SDCARD_MOUNT_DEVICE" ]; then + stat -c %N /sys/block/mmc* | grep mmc | cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" > /tmp/sdcard_block_devices + if [ -z `cat /tmp/sdcard_block_devices` ]; then + if [ -x /bin/whiptail ]; then + whiptail --title 'SDCARD Drive Missing' \ + --msgbox "Insert your SDCARD in memory card slot and press Enter to continue." 16 60 + else + echo "+++ SDCARD Missing! Insert your SDCARD in memory card slot and press Enter to continue." + read + fi + sleep 1 + stat -c %N /sys/block/mmc* | grep mmc | cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" > /tmp/sdcard_block_devices + if [ -z `cat /tmp/sdcard_block_devices` ]; then + if [ -x /bin/whiptail ]; then + whiptail $CONFIG_ERROR_BG_COLOR --title 'ERROR: SDCARD Missing' \ + --msgbox "SDCARD Missing! Aborting mount attempt.\n\nPress Enter to continue." 16 60 + else + echo "!!! ERROR: SDCARD in memory card slot Missing! Aborting mount. Press Enter to continue." + fi + exit 1 + fi + fi + + SDCARD_MOUNT_DEVICE="" + # Check for the common case: a single SDCARD disk with one partition + if [ `cat /tmp/sdcard_block_devices | wc -l` -eq 1 ]; then + SDCARD_BLOCK_DEVICE=`cat /tmp/sdcard_block_devices` + # Subtract out block device + let SDCARD_NUM_PARTITIONS=`ls -1 ${SDCARD_BLOCK_DEVICE}* | wc -l`-1 + if [ ${SDCARD_NUM_PARTITIONS} -eq 0 ]; then + SDCARD_MOUNT_DEVICE=${SDCARD_BLOCK_DEVICE} + elif [ ${SDCARD_NUM_PARTITIONS} -eq 1 ]; then + SDCARD_MOUNT_DEVICE=`ls -1 ${SDCARD_BLOCK_DEVICE}* | tail -n1` + fi + fi + # otherwise, let the user pick + if [ -z ${SDCARD_MOUNT_DEVICE} ]; then + > /tmp/sdcard_disk_list + for i in `cat /tmp/sdcard_block_devices`; do + # remove block device from list if numeric partitions exist, since not bootable + let SDCARD_NUM_PARTITIONS=`ls -1 $i* | wc -l`-1 + if [ ${SDCARD_NUM_PARTITIONS} -eq 0 ]; then + echo $i >> /tmp/sdcard_disk_list + else + ls $i* | tail -${SDCARD_NUM_PARTITIONS} >> /tmp/sdcard_disk_list + fi + done + + if [ -x /bin/whiptail ]; then + MENU_OPTIONS="" + n=0 + while read option + do + n=`expr $n + 1` + option=$(echo $option | tr " " "_") + MENU_OPTIONS="$MENU_OPTIONS $n ${option}" + done < /tmp/sdcard_disk_list + + MENU_OPTIONS="$MENU_OPTIONS a Abort" + whiptail --clear --title "Select your SDCARD disk" \ + --menu "Choose your SDCARD disk [1-$n, a to abort]:" 20 120 8 \ + -- $MENU_OPTIONS \ + 2>/tmp/whiptail + + option_index=$(cat /tmp/whiptail) + else + echo "+++ Select your SDCARD disk:" + n=0 + while read option + do + n=`expr $n + 1` + echo "$n. $option" + done < /tmp/sdcard_disk_list + + read \ + -p "Choose your SDCARD disk [1-$n, a to abort]: " \ + option_index + fi + + if [ "$option_index" = "a" ]; then + exit 1 + fi + SDCARD_MOUNT_DEVICE=`head -n $option_index /tmp/sdcard_disk_list | tail -1` + fi + fi + + #Check if $SDCARD_MOUNT_DEVICE is a LUKS encrypted device. If so, luksOpen it and replace $SDCARD_MOUNT_DEVICE with /dev/mapper/sdcarddev + is_Luks_luksOpen + if [ "$1" = "rw" ]; then + mount -o rw $SDCARD_MOUNT_DEVICE /media + else + mount -o ro $SDCARD_MOUNT_DEVICE /media + fi +fi From 379823df1ec2dfbda153710c1a402bfac9ed634c Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Fri, 7 Jun 2019 14:44:43 -0400 Subject: [PATCH 57/91] oem-provisioning attended one-shot filling of required information initrd/bin: factory-reset-nitrokey-libremkey.sh: cosmetic whiptail changes gui-init: Cosmetic changes and added TODOs. kexec-save-default: added TODOs mount-sdcard: added logic to properly bypass PCR5 mods when in OEM so we can add Disk Unlock Key. Added TODOs reencrypt-luks: Added logic to confirm to the user the presence of a bad sdcard. TODO: make it dynamic. initrd/etc/functions: - removed enable-sdcard, put it in mount-sdcard to mitigate PCR5 modification. See above. - added notify to show selected passphrases on screen - Cosmetic correction to Whiptail menu - Changed hardcoded EFF diceware sampling to 800 words on screen when manual mode is selected for passphrase gen. modules: cryptsetup: version bumped to 1.7.5 (latest) libgcrypt: GPG2 and cryptsetup dependency. version bumped to 1.8.4 (latest) patches/cryptsetup-1.7.5.patch: Copy of 1.7.3 as is Functional TODO: - kexec-save-default prompts to choose between /dev/mmcp0p2 and /dev/sda2.... Shortest fix would be to reuse /boot/kexec_key_devices.txt which points to /dev/sda2 per OEM prior setting of Disk Unlock Key. --- .../bin/factory-reset-nitrokey-libremkey.sh | 5 +- initrd/bin/gui-init | 27 ++++- initrd/bin/kexec-save-default | 5 + initrd/bin/mount-sdcard | 106 ++++++++++++++---- initrd/bin/reencrypt-luks | 54 +++++++-- initrd/etc/functions | 61 +++------- modules/cryptsetup | 4 +- modules/libgcrypt | 4 +- ...tup-1.7.3.patch => cryptsetup-1.7.5.patch} | 0 9 files changed, 184 insertions(+), 82 deletions(-) rename patches/{cryptsetup-1.7.3.patch => cryptsetup-1.7.5.patch} (100%) diff --git a/initrd/bin/factory-reset-nitrokey-libremkey.sh b/initrd/bin/factory-reset-nitrokey-libremkey.sh index 4eb27972e..574fea481 100755 --- a/initrd/bin/factory-reset-nitrokey-libremkey.sh +++ b/initrd/bin/factory-reset-nitrokey-libremkey.sh @@ -5,11 +5,8 @@ set -e -o pipefail . /tmp/config if (whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'Factory Reset and reownership of GPG card' \ - --yesno "You are about to factory reset your GPG card!\n\nThis will:\n 1-Wipe all PRIVATE keys that were previously kept inside GPG card\n 2-Set default key size to 4096 bits (maximum)\n 3-Ask you to choose two passwords to interact with the card:\n 3.1: An administrative passphrase used to manage the card\n 3.2: A user passphrase (PIN) used everytime you sign\n encrypt/decrypt content\n4-Generate new Encryption, Signing and Authentication keys\n inside your GPG card\n5-Export associated public key, replace the one being\n present and trusted inside running BIOS, and reflash\n the SPI flash with resulting rom image.\n\nAs a result, the running BIOS will be modified. Would you like to continue?" 30 90) then + --yesno "You are about to factory reset your GPG card!\n\nThis will:\n 1-Wipe all PRIVATE keys that were previously kept inside GPG card\n 2-Set default key size to 4096 bits (maximum)\n 3-Set two passwphrases to interact with the card:\n 3.1: An administrative passphrase used to manage the card\n 3.2: A user passphrase (PIN) used everytime you sign\n encrypt/decrypt content\n4-Generate new Encryption, Signing and Authentication keys\n inside your GPG smartcard\n5-Export associated public key into mounted /media/gpg_keys/, replace the one being\n present and trusted inside running BIOS, and reflash\n ROM with resulting image.\n\nAs a result, the running BIOS will be modified. Would you like to continue?" 30 90) then - whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'WARNING: Please Insert A USB Disk' --msgbox \ - "Please insert a USB disk on which you want to store your GPG public key\n and trustdb.\n\nThose will be backuped under the 'gpg_keys' directory.\n\nHit Enter to continue." 30 90 - mount-usb || die "Unable to mount USB device." #Copy generated public key, private_subkey, trustdb and artifacts to external media for backup: mount -o remount,rw /media || die "Unable to remount /media into Read Write mode. Is the device write protected?" diff --git a/initrd/bin/gui-init b/initrd/bin/gui-init index 4072ced68..68ab4f6d0 100755 --- a/initrd/bin/gui-init +++ b/initrd/bin/gui-init @@ -110,8 +110,7 @@ if [ -e /boot/oem ];then #Read /media/oem-provisioning file once to read provisioned secrets read_oem_files else - clear - notify "You must run the Reownership Wizard from a safe place with power outlet connected. OWM Reownership will require around an hour. Sytem will now power off." + notify "You must run the Reownership Wizard from a safe place with power outlet connected. OEM Reownership will require around an hour. Sytem will now power off." poweroff fi fi @@ -209,6 +208,30 @@ while true; do fi if [ "$totp_confirm" = "O" ]; then + #Taken from gui-init:verify_global_hashes() + # + #TODO: Fix checkup so that we give a report on /boot integrity if /boot/oem doesn't include gpg related tasks, which invalidates signature. + #The goal being to make sure nothing has been modified BUT /boot/oem. The rest should be intact. + # check_config only checks for kexec_* + # + # Check the hashes of all the files, ignoring signatures for now + #check_config /boot force + #TMP_HASH_FILE="/tmp/kexec/kexec_hashes.txt" + + #if cd /boot && sha256sum -c "$TMP_HASH_FILE" > /tmp/hash_output ; then + # HASH="OK" + #elif [ ! -f $TMP_HASH_FILE ]; then + # if (whiptail $CONFIG_ERROR_BG_COLOR --clear --title 'ERROR: Missing Hash File!' \ + # --yesno "The file containing hashes for /boot is missing!\n\nIf you are setting this system up for the first time, select Yes to update\nyour list of checksums.\n\nOtherwise this could indicate a compromise and you should select No to\nreturn to the main menu.\n\nWould you like to update your checksums now?" 30 90) then + # HASH="COMPROMISED" + # #update_checksums + # fi + # return 1 + # else + # CHANGED_FILES=$(grep -v 'OK$' /tmp/hash_output | cut -f1 -d ':') + # fi + + #TODO: modify TOTP HOTP lign to contain: HASH:OK/NOT OK whiptail $MAIN_MENU_BG_COLOR --clear --title "$CONFIG_BOOT_GUI_MENU_NAME: Reownership" \ --menu "Greenwich Mean Time (GMT) : $date\nTOTP: $TOTP | HOTP: $HOTP" 20 90 10 \ 'C' ' Continue ownership of devices' \ diff --git a/initrd/bin/kexec-save-default b/initrd/bin/kexec-save-default index 49e1cc382..4b8f86ec9 100755 --- a/initrd/bin/kexec-save-default +++ b/initrd/bin/kexec-save-default @@ -42,8 +42,13 @@ elif [ -z "$lvm_suggest" ]; then num_lvm=0 fi +#TODO: validate if "$device" or $device should be passed here. Think it should be $device so that we have a list of items on each line devices_suggest=$(blkid | cut -d ':' -f 1 | while read device;do cryptsetup isLuks "$device";if [ $(echo $?) == 0 ]; then echo "$device";fi; done | sort) +#TODO: shall we remove mmc device (OEM provisioning device) from encrypted boot device selection? +#devices_suggest_without_mmc=$(echo $devices_suggest|grep -v "mmc") +#devices_suggest="$devices_suggest_without_mmc" num_devices=$(echo "$devices_suggest"|wc -l) + if [ "$num_devices" -eq 1 ] && [ -s "$devices_suggest" ]; then key_devices=$devices_suggest else diff --git a/initrd/bin/mount-sdcard b/initrd/bin/mount-sdcard index 586c280a1..3014acf27 100755 --- a/initrd/bin/mount-sdcard +++ b/initrd/bin/mount-sdcard @@ -2,41 +2,110 @@ # Mount a SDCARD device . /etc/functions +enable_sdcard() +{ + #OEM ReOwnership Wizard, when attempting to load /media/oem-provisioning, + #requires mmc and sdhci kernel modules to be inserted here, which would + #normally modify PCR 5 by calling the /sbin/insmod wrapper, which + #measures the modules prior to loading them. + # + #We bypass those measurements here by calling busybox's insmod directly, + #keeping PCR5 intact so that calling kexec-seal-key (to add Disk Unlock Key) + #in OEM mode gives the same measurements then when calling kexec-unseal-key + #in normal boot mode after OEM reownership, making the release of the Disk + #Unlock Key consistent. + mount_boot + if [ -e /boot/oem ]; then + warn "Loading card reader (sdcard) related modules..." + #TODO: understand why conditional aliases don't work. It works on mount-usb :| + #alias insmod='busybox insmod' + #debug "Testing insmod in enable_sdcard just after alias: $(insmod)" + #even last debug happens after PCR5 being modified.... Changing tactic. Duplicating logic. + if [ "$CONFIG_LINUX_SDHCI" = "y" ]; then + if ! lsmod | grep -q mmc_core; then + busybox insmod /lib/modules/mmc_core.ko \ + || die "mmc_core: module load failed" + fi + if ! lsmod | grep -q mmc_block; then + busybox insmod /lib/modules/mmc_block.ko \ + || die "mmc_block: module load failed" + fi + if ! lsmod | grep -q sdhci; then + busybox insmod /lib/modules/sdhci.ko \ + || die "sdhci: module load failed" + fi + if ! lsmod | grep -q sdhci_pci; then + busybox insmod /lib/modules/sdhci-pci.ko \ + || die "sdhci-pci: module load failed" + fi + fi + else + #TODO: For some reason, the alias is not kept outside of the if so we replicate here with insmod which measures modules + if [ "$CONFIG_LINUX_SDHCI" = "y" ]; then + if ! lsmod | grep -q mmc_core; then + insmod /lib/modules/mmc_core.ko \ + || die "mmc_core: module load failed" + fi + if ! lsmod | grep -q mmc_block; then + insmod /lib/modules/mmc_block.ko \ + || die "mmc_block: module load failed" + fi + if ! lsmod | grep -q sdhci; then + insmod /lib/modules/sdhci.ko \ + || die "sdhci: module load failed" + fi + if ! lsmod | grep -q sdhci_pci; then + insmod /lib/modules/sdhci-pci.ko \ + || die "sdhci-pci: module load failed" + fi + fi + fi +} + is_Luks_luksOpen() { cryptsetup isLuks $SDCARD_MOUNT_DEVICE if [ $(echo $?) == 0 ]; then - echo -e "\n\nSDCARD Device $SDCARD_MOUNT_DEVICE is encrypted.\nPlease type $oem_name provided Disk Recovery Key passphrase at next prompt.\n" + echo -e "\n\nSDCARD Device $SDCARD_MOUNT_DEVICE is encrypted.\n" + + if [ -e /boot/oem ]; then + if ! grep -q luks_reencrypted /boot/oem ; then + echo -e "Please type provided $oem_name actual Disk Recovery Key passphrase at next prompt.\n" + else + echo -e "Please type your chosen new Disk Recovery Key passphrase at next prompt.\n" + fi + fi + cryptsetup luksOpen $SDCARD_MOUNT_DEVICE sdcarddev - if [ $(echo $?) == 0 ] && [ $(grep -q oem_provisioning_partition /boot/oem) ]; then - mount -o remount,rw /boot - echo "oem_provisioning_partition=$SDCARD_MOUNT_DEVICE" >> /boot/oem - mount -o remount,ro /boot + if [ $(echo $?) == 0 ]; then + mount_boot + if [ -e /boot/oem ]; then + if ! grep -q ^oem_provisioning_partition /boot/oem ; then + mount -o remount,rw /boot + echo "oem_provisioning_partition=$SDCARD_MOUNT_DEVICE" >> /boot/oem + mount -o remount,ro /boot + fi + fi fi SDCARD_MOUNT_DEVICE="/dev/mapper/sdcarddev" else clear - notify "OEM Reownership Wizard only supports provisioning to/from a LUKS encrypted partition. Please prepare such sdcard and try again. System will now power off." - poweroff + if [ -e /boot/oem ]; then + notify "OEM Reownership Wizard only supports auto-provisioning to/from a LUKS encrypted partition. Provisioning fallsback into manual mode. System will now power reboot." + mount -o remount,rw /boot + echo "no_automatic_provisioning" >> /boot/oem + mount -o remount,ro /boot + reboot + fi fi - } -#OEM reownership, when attempting to load /media/oem-provisioning, -#requires mmc and sdhci related module to be inserted through enable_sdcard. -#which would normally modify PCR 5 through /sbin/insmod script. -# -#We bypass those measurements here by calling busybox's insmod directly, -#keeping PCR5 intact so that calling kexec-seal-key (to add Disk Unlock Key) -#in OEM mode gives the same measurements then when calling kexec-unseal-key -#in normal boot mode after OEM reownership. if [ -e /boot/oem ]; then - alias insmod='busybox insmod' SDCARD_MOUNT_DEVICE=$(grep "^oem_provisioning_partition=" /boot/oem | cut -d "=" -f2) fi enable_sdcard -sleep 1 +sleep 1 if [ ! -d /media ]; then mkdir /media @@ -54,7 +123,6 @@ if ! grep -q /media /proc/mounts ; then echo "+++ SDCARD Missing! Insert your SDCARD in memory card slot and press Enter to continue." read fi - sleep 1 stat -c %N /sys/block/mmc* | grep mmc | cut -f1 -d ' ' | sed "s/[']//g;s|/sys/block|/dev|" > /tmp/sdcard_block_devices if [ -z `cat /tmp/sdcard_block_devices` ]; then if [ -x /bin/whiptail ]; then diff --git a/initrd/bin/reencrypt-luks b/initrd/bin/reencrypt-luks index f8edef512..7b71e471d 100755 --- a/initrd/bin/reencrypt-luks +++ b/initrd/bin/reencrypt-luks @@ -38,7 +38,7 @@ select_luks_container() } if [ -n "$reownership_state" ] && [ "$reownership_state" = "luks_reencryption" ]; then - #if no USB oem-privisioning file provides actual Disk Recovery Key + #if no oem-privisioning file provides actual Disk Recovery Key if [ -z "$oem_luks_actual_Disk_Recovery_Key" ]; then whiptail --title 'Reencrypt actual LUKS container with a new user selected strong passphrase?' \ --msgbox "This will replace the actual Disk Recovery Key.\n\nThe passphrase associated with this key will be asked to the user in the\n following conditions:\n1-Every boot if no Disk unlock key was added to the TPM\n2-If the TPM fails (Hardware failure)\n3-If the firmware has been tampered with/upgraded/modified by the user\n\nThis process requires you to type the actual Disk Recovery Key passphrase\nand will delete the actual Disk unlock key released by the TPM into\nLUKS (slot 1) if present.\n\nAt the next prompt, you may be asked to select which file corresponds to\nthe LUKS device container. Normally, it should be /dev/sda2.\n\nHit Enter to continue." 30 90 @@ -50,6 +50,7 @@ if [ -n "$reownership_state" ] && [ "$reownership_state" = "luks_reencryption" ] #USB "oem-privisioning" file provides actual Disk Recovery Key echo -n "$oem_luks_actual_Disk_Recovery_Key" > /tmp/oem_luks_actual_Disk_Recovery_Key select_luks_container + warn "Reencrypting "$LUKS" LUKS encrypted drive content with actual Recovery Disk Key passphrase..." cryptsetup-reencrypt -B 32 --use-directio "$LUKS" --key-slot 0 --key-file /tmp/oem_luks_actual_Disk_Recovery_Key fi @@ -64,6 +65,29 @@ if [ -n "$reownership_state" ] && [ "$reownership_state" = "luks_reencryption" ] else #Successfully reencrypted LUKS container with current Disk Recovery Key passphrase. Write successful state in oem file if [ -e /boot/oem ];then + #Reencrypting OEM provided sdcard + SDCARD_MOUNT_DEVICE=$(grep "^oem_provisioning_partition=" /boot/oem | cut -d "=" -f2) + if [ -n "$SDCARD_MOUNT_DEVICE" ]; then + umount /media 2> /dev/null + cryptsetup luksClose /dev/mapper/sdcarddev 2> /dev/null + warn "Reencrypting $SDCARD_MOUNT_DEVICE LUKS encrypted drive content with actual LUKS Recovery Disk Key passphrase..." + cryptsetup-reencrypt "$SDCARD_MOUNT_DEVICE" --key-slot 0 --key-file /tmp/oem_luks_actual_Disk_Recovery_Key + fi + if [ $(echo $?) -ne 0 ]; then + #TODO: Would be awesome to thread a watcher that would check in kernel output for sector errors and kill cryptsetup-reencrypt. + #Otherwise, reencrypting sdcard can take forever, and the result is corrupted LUKS container anyway.... + #For the moment, we catch it only when it fails. + warn "An error occured when reencrypting $SDCARD_MOUNT_DEVICE device. Probably sector corruption of unreliable sdcard flash..." + error "Outputing kernel log when ready:" + dmesg + warn "Unfortunately, the one-shot provisioning of OEM Reownership won't be able to provide automatic storing/fetching of credentials." + mount -o remount,rw /boot + echo "no_automatic_provisioning" >> /boot/oem + mount -o remount,ro /boot + warn "The OEM Reownership Wizard is now set to be fed manually by the user at each steps, without backup. Take notes of your secrets!" + error "Rebooting" + reboot + fi mount -o remount,rw /boot echo "luks_reencrypted" >> /boot/oem reownership_state="luks_password_change" @@ -75,17 +99,18 @@ if [ -n "$reownership_state" ] && [ "$reownership_state" = "luks_reencryption" ] fi if [ -n "$reownership_state" ] && [ "$reownership_state" = "luks_password_change" ]; then - #if actual or new Disk Recovery Key is not provisioned by USB oem-provisioning file + #if actual or new Disk Recovery Key is not provisioned by oem-provisioning file if [ -z "$oem_luks_actual_Disk_Recovery_Key" ] || [ -z "$oem_luks_new_Disk_Recovery_Key" ] ; then 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 select_luks_container cryptsetup luksChangeKey "$LUKS" --key-slot 0 --tries 3 else - #if actual and new Disk Recovery Key is provisioned by USB oem-provisioning file + #if actual and new Disk Recovery Key is provisioned by oem-provisioning file select_luks_container echo -n "$oem_luks_new_Disk_Recovery_Key" > /tmp/oem_luks_new_Disk_Recovery_Key echo -n "$oem_luks_actual_Disk_Recovery_Key" > /tmp/oem_luks_actual_Disk_Recovery_Key + warn "Changing "$LUKS" LUKS encrypted disk passphrase to new Disk Recovery Key passphrase..." cryptsetup luksChangeKey "$LUKS" --key-slot 0 --key-file=/tmp/oem_luks_actual_Disk_Recovery_Key /tmp/oem_luks_new_Disk_Recovery_Key fi #Validate past cryptsetup attempts @@ -93,19 +118,28 @@ if [ -n "$reownership_state" ] && [ "$reownership_state" = "luks_password_change #Cryptsetup was unsuccessful 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 - shred -n 10 -z -u /tmp/oem_luks_new_Disk_Recovery_Key 2> /dev/null - shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null else #Cryptsetup was successful - if [ -e /boot/oem ];then + if [ -e /boot/oem ]; then + SDCARD_MOUNT_DEVICE=$(grep "^oem_provisioning_partition=" /boot/oem | cut -d "=" -f2) + if [ -n "$SDCARD_MOUNT_DEVICE" ]; then + umount /media 2> /dev/null + cryptsetup luksClose /dev/mapper/sdcarddev 2> /dev/null + warn "Changing $SDCARD_MOUNT_DEVICE LUKS encrypted disk passphrase to new Recovery Disk Key passphrase..." + cryptsetup luksChangeKey "$SDCARD_MOUNT_DEVICE" --key-slot 0 --key-file=/tmp/oem_luks_actual_Disk_Recovery_Key /tmp/oem_luks_new_Disk_Recovery_Key + fi mount -o remount,rw /boot echo "luks_passwd_changed" >> /boot/oem mount -o remount,ro /boot - shred -n 10 -z -u /tmp/oem_luks_new_Disk_Recovery_Key 2> /dev/null - shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null - unset oem_luks_actual_Disk_Recovery_Key - unset oem_luks_new_Disk_Recovery_Key fi fi + #Cleanup + shred -n 10 -z -u /tmp/oem_luks_new_Disk_Recovery_Key 2> /dev/null + shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null + unset oem_luks_actual_Disk_Recovery_Key + unset oem_luks_new_Disk_Recovery_Key + notify "Your new Disk Recovery Key is now effective. The system will now reboot." + #TODO: Shall we set marker to set disk unlock key here? + reboot continue fi diff --git a/initrd/etc/functions b/initrd/etc/functions index 9d9863df2..da17af759 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -99,28 +99,6 @@ confirm_totp() echo } -enable_sdcard() -{ - if [ "$CONFIG_LINUX_SDHCI" = "y" ]; then - if ! lsmod | grep -q mmc_core; then - insmod /lib/modules/mmc_core.ko \ - || die "mmc_core: module load failed" - fi - if ! lsmod | grep -q mmc_block; then - insmod /lib/modules/mmc_block.ko \ - || die "mmc_block: module load failed" - fi - if ! lsmod | grep -q sdhci; then - insmod /lib/modules/sdhci.ko \ - || die "sdhci: module load failed" - fi - if ! lsmod | grep -q sdhci_pci; then - insmod /lib/modules/sdhci-pci.ko \ - || die "sdhci-pci: module load failed" - fi - fi -} - enable_usb() { if [ "$CONFIG_LINUX_USB_COMPANION_CONTROLLER" = y ]; then @@ -296,7 +274,8 @@ check_config() { if [ "$2" != "force" ]; then if ! sha256sum `find $1/kexec*.txt` | gpgv $1/kexec.sig - ; then die 'Invalid signature on kexec boot params. Investigate/Update checksums and sign all files in /boot.' - #TODO: Show which files failed integrity check! + #TODO: Show which files failed integrity check! copy logic from gui-init kexec-select-boot verify_global_hashes() + # Note: not here to do but in gui-init. But generic-init is lacking such info. fi fi @@ -340,7 +319,6 @@ combine_configs() { } read_oem_files() { - #TODO: check if /boot/oem contains past microsd disk and automount it. see tracing TODO below oem_name=$(grep "oem_name" /boot/oem | awk -F '=' {'print $2'}) if [ -n "$oem_name" ]; then export oem_name="$oem_name" @@ -351,7 +329,7 @@ read_oem_files() if ! [ $(grep "no_automatic_provisioning" /boot/oem) ]; then echo "Mounting memory card reader drive provision OEM reownership from /media/oem-provisioning..." - /bin/mount-sdcard || recovery "Unable to mount sdcard from memory card reader. Make sure the card is pushed in and type 'reboot' to continue." + mount-sdcard || recovery "Unable to mount sdcard from memory card reader. Make sure the card is pushed in and type 'reboot' to continue." if [ -e /media/oem-provisioning ]; then echo "Found /media/oem-provisioning. Parsing..." oem_gpg_Admin_PIN=$(grep "^oem_gpg_Admin_PIN=" /media/oem-provisioning | cut -d "=" -f2) @@ -528,11 +506,11 @@ read_oem_files() echo "Suggested passphrase length: 2 words diceware passphrase." randomize_diceware_passphrases_until_chosen_or_manual 2 UpperFirstLetter Nospace while [[ ${#passphrase} -lt 8 || ${#passphrase} -gt 20 ]] || [ "$passphrase" != "${passphrase% *}" ]; do - echo "We have limitations on Admin Pin: minimal 8 and maximal length of 20 characters, NO SPACE!" + echo "We have limitations on Admin PIN: minimal 8 and maximal length of 20 characters, NO SPACE!" validate_input_passphrases_are_equal done + notify "oem_gpg_Admin_PIN=$passphrase" export oem_gpg_Admin_PIN="$passphrase" - debug "oem_gpg_Admin_PIN=$oem_gpg_Admin_PIN" fi if [ "$to_provision" == "oem_gpg_User_PIN" ] ;then clear @@ -545,11 +523,11 @@ read_oem_files() echo "Suggested length: 2 random words diceware passphrase." randomize_diceware_passphrases_until_chosen_or_manual 2 UpperFirstLetter Nospace while [[ ${#passphrase} -lt 6 || ${#passphrase} -gt 20 ]]; do - echo "We have limitations for GPG Admin Pin: minimal 6 and maximal length of 20 characters" + echo "We have limitations for GPG User PIN: minimal 6 and maximal length of 20 characters" validate_input_passphrases_are_equal done + notify "oem_gpg_User_PIN=$passphrase" export oem_gpg_User_PIN="$passphrase" - debug "oem_gpg_User_PIN=$oem_gpg_User_PIN" fi if [ "$to_provision" == "oem_gpg_real_name" ]; then clear @@ -561,7 +539,6 @@ read_oem_files() validate_input_passphrases_are_equal done export oem_gpg_real_name="$passphrase" - debug "oem_gpg_real_name=$oem_gpg_real_name" fi if [ "$to_provision" == "oem_gpg_email" ]; then clear @@ -573,7 +550,6 @@ read_oem_files() validate_input_passphrases_are_equal done export oem_gpg_email="$passphrase" - debug "oem_gpg_email=$oem_gpg_email" fi if [ "$to_provision" == "oem_gpg_comment" ]; then clear @@ -586,7 +562,6 @@ read_oem_files() validate_input_passphrases_are_equal done export oem_gpg_comment="$passphrase" - debug "oem_gpg_comment=$oem_gpg_comment" fi if [ "$to_provision" == "oem_luks_actual_Disk_Recovery_Key" ]; then clear @@ -601,8 +576,8 @@ read_oem_files() echo "Make sure that this corresponds to the Disk Recovery Key passphrase provided by $oem_name." validate_input_passphrases_are_equal done + notify "oem_luks_actual_Disk_Recovery_Key=$passphrase" export oem_luks_actual_Disk_Recovery_Key="$passphrase" - debug "oem_luks_actual_Disk_Recovery_Key=$oem_luks_actual_Disk_Recovery_Key" #TODO: actual should be replaced by new LUKS recovery key after reencryption. fi if [ "$to_provision" == "oem_luks_new_Disk_Recovery_Key" ]; then @@ -623,8 +598,8 @@ read_oem_files() echo "Your brain remembers anything that is emotionnaly bonding. Create a story that your brain will remember." validate_input_passphrases_are_equal done + notify "oem_luks_new_Disk_Recovery_Key=$passphrase" export oem_luks_new_Disk_Recovery_Key="$passphrase" - debug "oem_luks_new_Disk_Recovery_Key=$oem_luks_new_Disk_Recovery_Key" fi if [ "$to_provision" == "oem_luks_Disk_Unlock_Key" ] && [ "$CONFIG_TPM" == "y" ] && [ "$CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY" == "y" ]; then @@ -644,7 +619,6 @@ read_oem_files() randomize_diceware_passphrases_until_chosen_or_manual 3 UpperFirstLetter Nospace validate_input_passphrases_are_equal export oem_luks_Disk_Unlock_Key="$passphrase" - debug "oem_luks_Disk_Unlock_Key=$oem_luks_Disk_Unlock_Key" fi if [ "$to_provision" == "oem_TPM_Owner_Password" ] && [ "$CONFIG_TPM" == "y" ]; then clear @@ -655,8 +629,8 @@ read_oem_files() echo "It is recommended to reuse GPG Admin Passphrase/Password here, to not unecessarily multiply secrets to remember." echo "We reused the GPG Admin PIN to set the TPM Owner Passphrase." oem_TPM_Owner_Password="$oem_gpg_Admin_PIN" + notify "oem_TPM_Owner_Password=$oem_gpg_Admin_PIN" export oem_TPM_Owner_Password="$oem_TPM_Owner_Password" - debug "oem_TPM_Owner_Password=$oem_TPM_Owner_Password" fi else echo "$to_provision is $provisioned_value." @@ -664,19 +638,21 @@ read_oem_files() done mount -o remount,rw /media - env|grep "oem_" | sort > /media/oem_provisioning + env|grep "oem_" > /media/oem-provisioning mount -o remount,ro /media else + #Provisiong the wizard once was refused mount -o remount,rw /boot echo "no_automatic_provisioning" >> /boot/oem mount -o remount,ro /boot - debug "no automatic provisioning" fi fi export oem_configuration_read=1 mount -o remount,ro /media fi + else + warn "'no_automatic_provisioning' flag found under /boot/oem. You'll have to enter provisioning information manually in the OEM Wizard." fi } @@ -688,7 +664,7 @@ check_onboarding_progress() if [ $? -ne 0 ];then #Show Onboarding menu once. whiptail --title 'Hardware reownership Wizard' --msgbox \ - "The received hardware is currently owned by $oem_name.\nWe will change that.\n\nThis Wizard will otherwise make you own your own hardware by:\n1-Reencrypting encrypted drive content (LUKS container)\n2-Changing LUKS Disk Recovery Key and it's passphrase\n3-Resetting your Librem Key/Nitrokey Pro v2 to factory defaults\n4-Setting User and Admin PINs into your Librem Key/NitroKey\n5-Generating keys in it, exporting public key and\n importing it in the ROM prior to reprogramming the SPI flash with it\n6-Taking integrity measures of all /boot files and sign the resulting\n checksum file with your Librem Key/Nitrokey Pro\n7-Reowning your Trusted Platform Module (TPM)\n\nScan the QR Code with an OTP app only after Reset the TPM last phase.\n\nHit Enter to continue." 20 20 + "The received hardware is currently owned by $oem_name.\nWe will change that.\n\nThis Wizard will otherwise make you own your own hardware by:\n1-Reencrypting encrypted drives content (LUKS containers)\n2-Changing their LUKS Disk Recovery Keys and their passphrases\n3-Resetting your Librem Key/Nitrokey Pro v2 to factory defaults\n4-Setting User and Admin PINs into your Librem Key/NitroKey\n5-Generating keys into its smartcard, exporting public key and\n importing it in the ROM prior to reprogramming the SPI flash with it\n6-Taking integrity measures of all /boot files and sign the resulting\n checksum file with your Librem Key/Nitrokey Pro\n7-Reowning your Trusted Platform Module (TPM)\n\nScan the QR Code with an OTP app only after Reset the TPM last phase.\n\nHit Enter to continue." 20 20 whiptail --title 'Hardware reownership Wizard' --msgbox \ "On the next screen, MAKE SURE THAT THE HOTP CODE IS: 'Success'\n\nIf it's not, reboot your hardware with your Librem/Nitrokey inserted.\n\nIf the HOTP code is still invalid, your hardware may been tampered with in\ntransit. Contact $oem_name." 20 20 totp_confirm="O" @@ -836,8 +812,9 @@ randomize_diceware_passphrases_until_chosen_or_manual() elif [ "$keep_passphrase" = "m" ]; then unset passphrase echo "It is suggested that you pick EFF diceware words to construct this passphrase." - echo "Shuffling EFF Diceware dictionary and sampling 1000 words out of it..." - diceware-eff.sh 1000 Capitalize + echo "Shuffling EFF Diceware dictionary and sampling words out of it..." + diceware-eff.sh 800 Capitalize + echo fi done } @@ -850,12 +827,10 @@ validate_input_passphrases_are_equal() read \ -p "Please type desired value: " \ passphrase1 - echo read \ -p "Please retype desired value: " \ passphrase2 - echo if [ "$passphrase1" != "$passphrase2" ] || [ -z "$passphrase1" ]; then echo "Entered value were different. Please type them again so they match." diff --git a/modules/cryptsetup b/modules/cryptsetup index 4cea7f359..7db12b212 100644 --- a/modules/cryptsetup +++ b/modules/cryptsetup @@ -2,11 +2,11 @@ modules-$(CONFIG_CRYPTSETUP) += cryptsetup cryptsetup_depends := util-linux popt lvm2 $(musl_dep) -cryptsetup_version := 1.7.3 +cryptsetup_version := 1.7.5 cryptsetup_dir := cryptsetup-$(cryptsetup_version) cryptsetup_tar := cryptsetup-$(cryptsetup_version).tar.xz cryptsetup_url := https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-$(cryptsetup_version).tar.xz -cryptsetup_hash := af2b04e8475cf40b8d9ffd97a1acfa73aa787c890430afd89804fb544d6adc02 +cryptsetup_hash := 2b30cd1d0dd606a53ac77b406e1d37798d4b0762fa89de6ea546201906a251bd # Use an empty prefix so that the executables will not include the # build path. diff --git a/modules/libgcrypt b/modules/libgcrypt index d3c9dab4a..862627576 100644 --- a/modules/libgcrypt +++ b/modules/libgcrypt @@ -1,9 +1,9 @@ modules-$(CONFIG_GPG2) += libgcrypt -libgcrypt_version := 1.8.3 +libgcrypt_version := 1.8.4 libgcrypt_dir := libgcrypt-$(libgcrypt_version) libgcrypt_tar := libgcrypt-$(libgcrypt_version).tar.bz2 libgcrypt_url := https://gnupg.org/ftp/gcrypt/libgcrypt/$(libgcrypt_tar) -libgcrypt_hash := 66ec90be036747602f2b48f98312361a9180c97c68a690a5f376fa0f67d0af7c +libgcrypt_hash := f638143a0672628fde0cad745e9b14deb85dffb175709cacc1f4fe24b93f2227 libgcrypt_configure := ./configure \ $(CROSS_TOOLS) \ diff --git a/patches/cryptsetup-1.7.3.patch b/patches/cryptsetup-1.7.5.patch similarity index 100% rename from patches/cryptsetup-1.7.3.patch rename to patches/cryptsetup-1.7.5.patch From ce799d14959ccc360e2fafa92dca4abdb726d59b Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Fri, 7 Jun 2019 18:39:33 -0400 Subject: [PATCH 58/91] reencrypt-luks: aesthetic fixes --- initrd/bin/reencrypt-luks | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/initrd/bin/reencrypt-luks b/initrd/bin/reencrypt-luks index 7b71e471d..63f30c1d8 100755 --- a/initrd/bin/reencrypt-luks +++ b/initrd/bin/reencrypt-luks @@ -138,7 +138,7 @@ if [ -n "$reownership_state" ] && [ "$reownership_state" = "luks_password_change shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null unset oem_luks_actual_Disk_Recovery_Key unset oem_luks_new_Disk_Recovery_Key - notify "Your new Disk Recovery Key is now effective. The system will now reboot." + notify "Your new Disk Recovery Key and its passphrase is now effective and replaced old ones. The system will now reboot." #TODO: Shall we set marker to set disk unlock key here? reboot continue From faddca3f1cf1c4748c6bc0882f25a09615d1db76 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Fri, 7 Jun 2019 18:40:39 -0400 Subject: [PATCH 59/91] kexec-save-default: fix luks device proposition by proposing existing ones prior to suggested ones. --- initrd/bin/kexec-save-default | 90 +++++++++++++++++------------------ 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/initrd/bin/kexec-save-default b/initrd/bin/kexec-save-default index 4b8f86ec9..fab01bded 100755 --- a/initrd/bin/kexec-save-default +++ b/initrd/bin/kexec-save-default @@ -33,6 +33,9 @@ TMP_MENU_FILE="/tmp/kexec/kexec_menu.txt" ENTRY_FILE="$paramsdir/kexec_default.$index.txt" HASH_FILE="$paramsdir/kexec_default_hashes.txt" +KEY_DEVICES="$paramsdir/kexec_key_devices.txt" +KEY_LVM="$paramsdir/kexec_key_lvm.txt" + lvm_suggest=$(lvm vgscan|awk -F '"' {'print $1'}|tail -n +2) num_lvm=$(echo "$lvm_suggest"|wc -l) @@ -42,7 +45,6 @@ elif [ -z "$lvm_suggest" ]; then num_lvm=0 fi -#TODO: validate if "$device" or $device should be passed here. Think it should be $device so that we have a list of items on each line devices_suggest=$(blkid | cut -d ':' -f 1 | while read device;do cryptsetup isLuks "$device";if [ $(echo $?) == 0 ]; then echo "$device";fi; done | sort) #TODO: shall we remove mmc device (OEM provisioning device) from encrypted boot device selection? #devices_suggest_without_mmc=$(echo $devices_suggest|grep -v "mmc") @@ -55,47 +57,6 @@ else devices_suggest=$(echo $devices_suggest) fi -if [ "$num_lvm" -gt 1 ]; then - //untested - selected_lvmdev_not_existing=1 - while [ $selected_lvmdev_not_existing -ne 0 ];do - { - read \ - -p "Encrypted LVM group? choose between: $lvm_suggest: " \ - lvm_volume_group - - result=$(echo "$lvm_suggest" | grep -q "$lvm_volume_group") || selected_lvmdev_not_existing=1 - if [ $? == 0 ]; then - selected_lvmdev_not_existing=0 - fi - };done -elif [ "$num_lvm" -eq 1 ] && [ -s $lvm_suggest ]; then - echo "Single Encrypted LVM group found at $lvm_suggest." - lvm_volume_group=$lvm_suggest -else - echo "No encrypted LVM Group found." -fi - -if [ "$num_devices" -gt 1 ]; then - selected_luksdev_not_existing=1 - while [ $selected_luksdev_not_existing -ne 0 ];do - { - read \ - -p "Encrypted devices? (choose between: $devices_suggest): " \ - key_devices - - result=$(echo "$devices_suggest" | grep -q "$key_devices") || selected_luksdev_not_existing=1 - if [ $? == 0 ]; then - selected_luksdev_not_existing=0 - fi - };done -elif [ "$num_devices" -eq 1 ]; then - echo "Single Encrypted Disk found at $devices_suggest." - key_devices=$devices_suggest -else - echo "No encrypted devices found." -fi - if [ "$num_lvm" -eq 0 ] && [ "$num_devices" -eq 0 ]; then #No encrypted partition found. no_encrypted_partition=1 @@ -110,8 +71,6 @@ if [ -z "$entry" ]; then die "Invalid menu index $index" fi -KEY_DEVICES="$paramsdir/kexec_key_devices.txt" -KEY_LVM="$paramsdir/kexec_key_lvm.txt" save_key="n" if [ "$CONFIG_TPM" = "y" ] && [ "$CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY" = "y" ] && [ "$no_encrypted_partition" != "1" ]; then @@ -172,7 +131,48 @@ if [ "$CONFIG_TPM" = "y" ] && [ "$CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY" = "y" ] lvm_volume_group="$old_lvm_volume_group" fi fi - fi + else + if [ "$num_lvm" -gt 1 ]; then + //untested + selected_lvmdev_not_existing=1 + while [ $selected_lvmdev_not_existing -ne 0 ];do + { + read \ + -p "Encrypted LVM group? choose between: $lvm_suggest: " \ + lvm_volume_group + + result=$(echo "$lvm_suggest" | grep -q "$lvm_volume_group") || selected_lvmdev_not_existing=1 + if [ $? == 0 ]; then + selected_lvmdev_not_existing=0 + fi + };done + elif [ "$num_lvm" -eq 1 ] && [ -s $lvm_suggest ]; then + echo "Single Encrypted LVM group found at $lvm_suggest." + lvm_volume_group=$lvm_suggest + else + echo "No encrypted LVM Group found." + fi + + if [ "$num_devices" -gt 1 ]; then + selected_luksdev_not_existing=1 + while [ $selected_luksdev_not_existing -ne 0 ];do + { + read \ + -p "Encrypted devices? (choose between: $devices_suggest): " \ + key_devices + + result=$(echo "$devices_suggest" | grep -q "$key_devices") || selected_luksdev_not_existing=1 + if [ $? == 0 ]; then + selected_luksdev_not_existing=0 + fi + };done + elif [ "$num_devices" -eq 1 ]; then + echo "Single Encrypted Disk found at $devices_suggest." + key_devices=$devices_suggest + else + echo "No encrypted devices found." + fi + fi save_key_params="-s -p $paramsdev" if [ -n "$lvm_volume_group" ]; then From 00fbd9cf6fdc2ee69cd91191f8b0ca399c504924 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sat, 8 Jun 2019 11:50:47 -0400 Subject: [PATCH 60/91] qemu: reverting changes that were needed for testing OEM-Reownership --- boards/qemu-coreboot/qemu-coreboot.config | 18 ++++++++---------- config/coreboot-qemu.config | 1 - initrd/boot/oem | 0 3 files changed, 8 insertions(+), 11 deletions(-) delete mode 100644 initrd/boot/oem diff --git a/boards/qemu-coreboot/qemu-coreboot.config b/boards/qemu-coreboot/qemu-coreboot.config index 026aa2a24..d670dc21a 100644 --- a/boards/qemu-coreboot/qemu-coreboot.config +++ b/boards/qemu-coreboot/qemu-coreboot.config @@ -24,12 +24,12 @@ CONFIG_DROPBEAR=y #Uncomment only one of the following block #Required for graphical gui-init (FBWhiptail) -CONFIG_CAIRO=y -CONFIG_FBWHIPTAIL=y +#CONFIG_CAIRO=y +#CONFIG_FBWHIPTAIL=y # #text-based init (generic-init and gui-init) -#CONFIG_NEWT=y -#CONFIG_SLANG=y +CONFIG_NEWT=y +CONFIG_SLANG=y endif @@ -40,17 +40,15 @@ CONFIG_LINUX_E1000=y #Uncomment only one BOOTSCRIPT: #Whiptail-based init (text-based or FBWhiptail) -export CONFIG_BOOTSCRIPT=/bin/gui-init +#export CONFIG_BOOTSCRIPT=/bin/gui-init # #text-based original init: -#export CONFIG_BOOTSCRIPT=/bin/generic-init +export CONFIG_BOOTSCRIPT=/bin/generic-init export CONFIG_TPM=n -export CONFIG_BOOT_DEV="/boot.img" -export CONFIG_USB_BOOT_DEV="/media.img" -export CONFIG_BOOT_KERNEL_ADD="nohz=on" - +export CONFIG_BOOT_DEV="/dev/sda1" +export CONFIG_USB_BOOT_DEV="/dev/sdb1" #run: coreboot.intermediate run: diff --git a/config/coreboot-qemu.config b/config/coreboot-qemu.config index 78dd08a3e..cfccf5269 100644 --- a/config/coreboot-qemu.config +++ b/config/coreboot-qemu.config @@ -13,6 +13,5 @@ CONFIG_CPU_MICROCODE_CBFS_GENERATE=y # CONFIG_CONSOLE_SERIAL is not set CONFIG_DEFAULT_CONSOLE_LOGLEVEL_6=y CONFIG_PAYLOAD_LINUX=y -CONFIG_LINUX_COMMAND_LINE="nohz=on" CONFIG_PAYLOAD_FILE="../../build/qemu-coreboot/bzImage" CONFIG_LINUX_INITRD="../../build/qemu-coreboot/initrd.cpio.xz" diff --git a/initrd/boot/oem b/initrd/boot/oem deleted file mode 100644 index e69de29bb..000000000 From 2cd5c48d19031520e5e8143b0ec02aef09938bf3 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sat, 8 Jun 2019 11:51:52 -0400 Subject: [PATCH 61/91] Cosmetic changes --- initrd/bin/flash.sh | 2 +- initrd/bin/gui-init | 2 +- initrd/bin/kexec-save-default | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/initrd/bin/flash.sh b/initrd/bin/flash.sh index 6b7ad02d2..265c73bc3 100755 --- a/initrd/bin/flash.sh +++ b/initrd/bin/flash.sh @@ -49,7 +49,7 @@ flash_rom() { if [ -e /boot/kexec_key_devices.txt ] || [ -e /boot/kexec_key_lvm.txt ]; then echo -e "\n\nBoth your TOTP/HOTP codes and TPM released Disk Unlock Key were invalidated since measured boot integrity changed." - echo -e "You will be requested to reseal TOTP/HOTP secrets, to set a new default boot option and define a new Disk Unlock Key passphrase.\n\n" + notify "You will be requested to reseal TOTP/HOTP secrets, to set a new default boot option and define a new Disk Unlock Key passphrase.\n\n" mount_boot mount -o remount,rw /boot touch /boot/reset_disk_unlock_key diff --git a/initrd/bin/gui-init b/initrd/bin/gui-init index 431bf7d1f..158a0cffc 100755 --- a/initrd/bin/gui-init +++ b/initrd/bin/gui-init @@ -234,7 +234,7 @@ while true; do # CHANGED_FILES=$(grep -v 'OK$' /tmp/hash_output | cut -f1 -d ':') # fi - #TODO: modify TOTP HOTP lign to contain: HASH:OK/NOT OK + #TODO: modify TOTP HOTP line to contain: HASH:OK/NOT OK whiptail $MAIN_MENU_BG_COLOR --clear --title "$CONFIG_BOOT_GUI_MENU_NAME: Reownership" \ --menu "Greenwich Mean Time (GMT) : $date\nTOTP: $TOTP | HOTP: $HOTP" 20 90 10 \ 'C' ' Continue ownership of devices' \ diff --git a/initrd/bin/kexec-save-default b/initrd/bin/kexec-save-default index fab01bded..305fbf0f2 100755 --- a/initrd/bin/kexec-save-default +++ b/initrd/bin/kexec-save-default @@ -49,6 +49,8 @@ devices_suggest=$(blkid | cut -d ':' -f 1 | while read device;do cryptsetup isLu #TODO: shall we remove mmc device (OEM provisioning device) from encrypted boot device selection? #devices_suggest_without_mmc=$(echo $devices_suggest|grep -v "mmc") #devices_suggest="$devices_suggest_without_mmc" +#NOW: mitgated by taking prior existing envrypted devices. +#Requires the OEM to set a LUKS Disk Unlock passphrase, which outputs current encrypted device under /boot/kexec_key_devices num_devices=$(echo "$devices_suggest"|wc -l) if [ "$num_devices" -eq 1 ] && [ -s "$devices_suggest" ]; then From c5d07829e7a745c5744ebaead2b05231fd8d690c Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sat, 8 Jun 2019 20:07:03 -0400 Subject: [PATCH 62/91] OEM Reownership now validates signed hash integrity + gui-init: Respect accepted ordering in Configuration menu, while adding Reencyption option (and readded forgotten x: recovery shell option in resolving conficts) + Fix (forgotten fi that made gui-init not work) --- initrd/bin/gui-init | 41 ++++++++++++++--------------------------- 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/initrd/bin/gui-init b/initrd/bin/gui-init index 158a0cffc..b2c7d83d7 100755 --- a/initrd/bin/gui-init +++ b/initrd/bin/gui-init @@ -211,32 +211,17 @@ while true; do fi if [ "$totp_confirm" = "O" ]; then - #Taken from gui-init:verify_global_hashes() - # - #TODO: Fix checkup so that we give a report on /boot integrity if /boot/oem doesn't include gpg related tasks, which invalidates signature. - #The goal being to make sure nothing has been modified BUT /boot/oem. The rest should be intact. - # check_config only checks for kexec_* - # - # Check the hashes of all the files, ignoring signatures for now - #check_config /boot force - #TMP_HASH_FILE="/tmp/kexec/kexec_hashes.txt" - - #if cd /boot && sha256sum -c "$TMP_HASH_FILE" > /tmp/hash_output ; then - # HASH="OK" - #elif [ ! -f $TMP_HASH_FILE ]; then - # if (whiptail $CONFIG_ERROR_BG_COLOR --clear --title 'ERROR: Missing Hash File!' \ - # --yesno "The file containing hashes for /boot is missing!\n\nIf you are setting this system up for the first time, select Yes to update\nyour list of checksums.\n\nOtherwise this could indicate a compromise and you should select No to\nreturn to the main menu.\n\nWould you like to update your checksums now?" 30 90) then - # HASH="COMPROMISED" - # #update_checksums - # fi - # return 1 - # else - # CHANGED_FILES=$(grep -v 'OK$' /tmp/hash_output | cut -f1 -d ':') - # fi + check_config /boot force + TMP_HASH_FILE="/tmp/kexec/kexec_hashes.txt" + + if cd /boot && sha256sum -c "$TMP_HASH_FILE" > /tmp/hash_output ; then + HASH="OK" + else + HASH="ALTERED" + fi - #TODO: modify TOTP HOTP line to contain: HASH:OK/NOT OK whiptail $MAIN_MENU_BG_COLOR --clear --title "$CONFIG_BOOT_GUI_MENU_NAME: Reownership" \ - --menu "Greenwich Mean Time (GMT) : $date\nTOTP: $TOTP | HOTP: $HOTP" 20 90 10 \ + --menu "Greenwich Mean Time (GMT) : $date\nTOTP: $TOTP | HOTP: $HOTP | HASHES: $HASH" 20 90 10 \ 'C' ' Continue ownership of devices' \ 'x' ' Exit to recovery shell' \ 2>/tmp/whiptail || recovery "GUI menu failed" @@ -252,11 +237,12 @@ while true; do --menu "Configure Settings" 20 90 10 \ 'o' ' Other Boot Options -->' \ 't' ' TPM/TOTP/HOTP Options -->' \ - 'G' ' GPG Options -->' \ - 'f' ' Flash/Update the BIOS -->' \ - 'c' ' Change configuration settings -->' \ 's' ' Update checksums and sign all files in /boot' \ + 'c' ' Change configuration settings -->' \ + 'f' ' Flash/Update the BIOS -->' \ + 'G' ' GPG Options -->' \ 'R' ' Reencrypt LUKS container' \ + 'x' ' Exit to recovery shell' \ 'r' ' <-- Return to main menu' \ 2>/tmp/whiptail || recovery "GUI menu failed" @@ -407,6 +393,7 @@ while true; do if [ "$totp_confirm" = "R" ]; then /bin/reencrypt-luks continue + fi if [ "$totp_confirm" = "P" ]; then poweroff From 96e262135e3c7a7a81c297ef50a3f95a0cd8869c Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sat, 8 Jun 2019 20:39:53 -0400 Subject: [PATCH 63/91] gui-init: Hash validation happens in /boot. chdir to / So that cryptsetup-reencryption works again. Else logs attempts to be created under /boot, resulting in cryptsetup-reencrypt to exit, not being able to create log --- initrd/bin/gui-init | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/initrd/bin/gui-init b/initrd/bin/gui-init index b2c7d83d7..2c9908b96 100755 --- a/initrd/bin/gui-init +++ b/initrd/bin/gui-init @@ -215,7 +215,9 @@ while true; do TMP_HASH_FILE="/tmp/kexec/kexec_hashes.txt" if cd /boot && sha256sum -c "$TMP_HASH_FILE" > /tmp/hash_output ; then - HASH="OK" + HASH="OK" + #Else there is errors from cryptsetup-reencrypt complaining to not be able to create logfile + cd / else HASH="ALTERED" fi From 919b46eaeeb52b3ad12a7425ccc95461cb1e803e Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sat, 8 Jun 2019 21:05:57 -0400 Subject: [PATCH 64/91] cosmetic whiptail changes --- initrd/bin/factory-reset-nitrokey-libremkey.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/initrd/bin/factory-reset-nitrokey-libremkey.sh b/initrd/bin/factory-reset-nitrokey-libremkey.sh index 574fea481..bf47cdc18 100755 --- a/initrd/bin/factory-reset-nitrokey-libremkey.sh +++ b/initrd/bin/factory-reset-nitrokey-libremkey.sh @@ -5,7 +5,7 @@ set -e -o pipefail . /tmp/config if (whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'Factory Reset and reownership of GPG card' \ - --yesno "You are about to factory reset your GPG card!\n\nThis will:\n 1-Wipe all PRIVATE keys that were previously kept inside GPG card\n 2-Set default key size to 4096 bits (maximum)\n 3-Set two passwphrases to interact with the card:\n 3.1: An administrative passphrase used to manage the card\n 3.2: A user passphrase (PIN) used everytime you sign\n encrypt/decrypt content\n4-Generate new Encryption, Signing and Authentication keys\n inside your GPG smartcard\n5-Export associated public key into mounted /media/gpg_keys/, replace the one being\n present and trusted inside running BIOS, and reflash\n ROM with resulting image.\n\nAs a result, the running BIOS will be modified. Would you like to continue?" 30 90) then + --yesno "You are about to factory reset your GPG card!\n\nThis will:\n 1-Wipe all PRIVATE keys that were previously kept inside GPG card\n 2-Set default key size to 4096 bits (maximum)\n 3-Set two passwphrases to interact with the card:\n 3.1: An administrative passphrase used to manage the card\n 3.2: A user passphrase (PIN) used everytime you sign\n encrypt/decrypt content\n4-Generate new Encryption, Signing and Authentication keys\n inside your GPG smartcard\n5-Export associated public key into mounted /media/gpg_keys/, replace the\n one being present and trusted inside running BIOS, and reflash\n ROM with resulting image.\n\nAs a result, the running BIOS will be modified. Would you like to continue?" 30 90) then mount-usb || die "Unable to mount USB device." #Copy generated public key, private_subkey, trustdb and artifacts to external media for backup: From e0cf0cec53e1f8c1d7feb8f2f2e41da3f06f5c28 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sat, 8 Jun 2019 22:35:22 -0400 Subject: [PATCH 65/91] Typo corrections --- initrd/bin/flash.sh | 2 +- initrd/bin/gui-init | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/initrd/bin/flash.sh b/initrd/bin/flash.sh index 265c73bc3..9c4d9f2e8 100755 --- a/initrd/bin/flash.sh +++ b/initrd/bin/flash.sh @@ -49,7 +49,7 @@ flash_rom() { if [ -e /boot/kexec_key_devices.txt ] || [ -e /boot/kexec_key_lvm.txt ]; then echo -e "\n\nBoth your TOTP/HOTP codes and TPM released Disk Unlock Key were invalidated since measured boot integrity changed." - notify "You will be requested to reseal TOTP/HOTP secrets, to set a new default boot option and define a new Disk Unlock Key passphrase.\n\n" + notify "You will be requested to reseal TOTP/HOTP secrets, to set a new default boot option and define a new Disk Unlock Key passphrase." mount_boot mount -o remount,rw /boot touch /boot/reset_disk_unlock_key diff --git a/initrd/bin/gui-init b/initrd/bin/gui-init index 2c9908b96..4686787bf 100755 --- a/initrd/bin/gui-init +++ b/initrd/bin/gui-init @@ -217,7 +217,7 @@ while true; do if cd /boot && sha256sum -c "$TMP_HASH_FILE" > /tmp/hash_output ; then HASH="OK" #Else there is errors from cryptsetup-reencrypt complaining to not be able to create logfile - cd / + cd / else HASH="ALTERED" fi From 0b348f13734f72ef05fd4e3108e99907898c6383 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Tue, 11 Jun 2019 13:54:08 -0400 Subject: [PATCH 66/91] Reverting LIBREMKEY dependence on x230.config board. Creating x230-libremkey board config. --- boards/x230-libremkey/x230-libremkey.config | 50 +++++++++++++++++++++ boards/x230/x230.config | 2 +- 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 boards/x230-libremkey/x230-libremkey.config diff --git a/boards/x230-libremkey/x230-libremkey.config b/boards/x230-libremkey/x230-libremkey.config new file mode 100644 index 000000000..11f14eae4 --- /dev/null +++ b/boards/x230-libremkey/x230-libremkey.config @@ -0,0 +1,50 @@ +# Configuration for a x230 with Librem Key, running Qubes and other OSes +export CONFIG_COREBOOT=y +CONFIG_COREBOOT_CONFIG=config/coreboot-x230.config +CONFIG_LINUX_CONFIG=config/linux-x230.config + +CONFIG_CRYPTSETUP=y +CONFIG_FLASHROM=y +CONFIG_FLASHTOOLS=y +CONFIG_GPG2=y +CONFIG_KEXEC=y +CONFIG_UTIL_LINUX=y +CONFIG_LVM2=y +CONFIG_MBEDTLS=y +CONFIG_PCIUTILS=y +CONFIG_POPT=y +CONFIG_QRENCODE=y +CONFIG_TPMTOTP=y +CONFIG_DROPBEAR=y + +#CONFIG_SLANG=y +#CONFIG_NEWT=y +CONFIG_CAIRO=y +CONFIG_FBWHIPTAIL=y +CONFIG_LIBREMKEY=y + +CONFIG_LINUX_USB=y +CONFIG_LINUX_E1000E=y +export CONFIG_LINUX_SDHCI=y + +export CONFIG_TPM=y +export CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY=y + +export CONFIG_BOOTSCRIPT=/bin/gui-init +export CONFIG_BOOT_REQ_HASH=n +export CONFIG_BOOT_REQ_ROLLBACK=n +export CONFIG_BOOT_KERNEL_ADD="intel_iommu=on intel_iommu=igfx_off" +export CONFIG_BOOT_KERNEL_REMOVE="" +export CONFIG_BOOT_DEV="/dev/sda1" +export CONFIG_BOOT_GUI_MENU_NAME="Thinkpad X230 Heads Boot Menu" +export CONFIG_USB_BOOT_DEV="/dev/sdb1" +export CONFIG_WARNING_BG_COLOR="--background-gradient 0 0 0 150 125 0" +export CONFIG_ERROR_BG_COLOR="--background-gradient 0 0 0 150 0 0" + +# This board has two SPI flash chips, an 8 MB that holds the IFD, +# the ME image and part of the coreboot image, and a 4 MB one that +# has the rest of the coreboot and the reset vector. +# +# Only flashing to the bios region is safe to do. The easiest is to +# flash internally when the IFD is unlocked for writing, and x230-flash +# is installed first. diff --git a/boards/x230/x230.config b/boards/x230/x230.config index a2c993af1..c9c9426d2 100644 --- a/boards/x230/x230.config +++ b/boards/x230/x230.config @@ -21,7 +21,7 @@ CONFIG_DROPBEAR=y #CONFIG_NEWT=y CONFIG_CAIRO=y CONFIG_FBWHIPTAIL=y -CONFIG_LIBREMKEY=y +#CONFIG_LIBREMKEY=y CONFIG_LINUX_USB=y CONFIG_LINUX_E1000E=y From e7a2ceddcd1ff7ce2ec85d3680537065a129e4f5 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Tue, 11 Jun 2019 13:58:30 -0400 Subject: [PATCH 67/91] Change Nitrokey/Librem Key references to Librem Key only to remove confusion. + cosmetic changes. + WiP to boot on SDCARD (debug todo) --- ...ibremkey.sh => factory-reset-libremkey.sh} | 0 initrd/bin/gpg-gui.sh | 4 +-- initrd/bin/gui-init | 18 +++++++++---- initrd/bin/kexec-seal-key | 4 +-- initrd/bin/reencrypt-luks | 2 +- initrd/bin/seal-libremkey | 10 ++++---- initrd/etc/functions | 25 +++++++++---------- 7 files changed, 35 insertions(+), 28 deletions(-) rename initrd/bin/{factory-reset-nitrokey-libremkey.sh => factory-reset-libremkey.sh} (100%) diff --git a/initrd/bin/factory-reset-nitrokey-libremkey.sh b/initrd/bin/factory-reset-libremkey.sh similarity index 100% rename from initrd/bin/factory-reset-nitrokey-libremkey.sh rename to initrd/bin/factory-reset-libremkey.sh diff --git a/initrd/bin/gpg-gui.sh b/initrd/bin/gpg-gui.sh index 6ffe67885..1d8b06564 100755 --- a/initrd/bin/gpg-gui.sh +++ b/initrd/bin/gpg-gui.sh @@ -108,7 +108,7 @@ while true; do 'l' ' List GPG keys in your keyring' \ 'm' ' Manually generate GPG keys on a USB security token' \ 'o' ' OEM Factory reset + auto keygen USB security token' \ - 'F' ' Factory Reset Librem Key/Nitrokey Pro v2 GPG Card + keygen + flash' \ + 'F' ' Factory Reset Librem Key GPG Card + keygen + flash' \ 'x' ' Exit' \ 2>/tmp/whiptail || recovery "GUI menu failed" @@ -215,7 +215,7 @@ while true; do fi ;; "F" ) - /bin/factory-reset-nitrokey-libremkey.sh + /bin/factory-reset-libremkey.sh ;; esac diff --git a/initrd/bin/gui-init b/initrd/bin/gui-init index 4686787bf..27119bc56 100755 --- a/initrd/bin/gui-init +++ b/initrd/bin/gui-init @@ -87,12 +87,12 @@ update_totp() echo "Scan the QR code to add the new TOTP secret" /bin/seal-totp $CONFIG_BOARD if [ -x /bin/libremkey_hotp_verification ]; then - echo "Once you have scanned the QR code, hit Enter to configure your Librem Key/Nitrokey" + echo "Once you have scanned the QR code, hit Enter to configure your Librem Key." read /bin/seal-libremkey #Sometimes HOTP sealing fails. We do until it works. while [ $? -ne 0 ];do - echo -e "\n\nSealing HOTP secret into Librem Key/Nitrokey failed. Let's try again by resealing both TOTP and HOTP." + echo -e "\n\nSealing HOTP secret into Librem Key failed. Let's try again by resealing both TOTP and HOTP." update_totp /bin/seal-libremkey done @@ -172,7 +172,7 @@ while true; do HOTP=`unseal-hotp` enable_usb if ! libremkey_hotp_verification info ; then - whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'WARNING: Please Insert Your Librem Key/Nitrokey' --msgbox "Your Librem Key/Nitrokey was not detected.\n\nPlease insert your Librem Key/Nitrokey" 30 90 + whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'WARNING: Please Insert Your Librem Key ' --msgbox "Your Librem Key was not detected.\n\nPlease insert your Librem Key" 30 90 fi # Don't output HOTP codes to screen, so as to make replay attacks harder libremkey_hotp_verification check "$HOTP" @@ -185,7 +185,7 @@ while true; do MAIN_MENU_BG_COLOR=$CONFIG_ERROR_BG_COLOR ;; * ) - HOTP="Error checking code, Insert Librem Key/Nitrokey and retry" + HOTP="Error checking code, Insert Librem Key and retry" MAIN_MENU_BG_COLOR=$CONFIG_WARNING_BG_COLOR ;; esac @@ -223,7 +223,7 @@ while true; do fi whiptail $MAIN_MENU_BG_COLOR --clear --title "$CONFIG_BOOT_GUI_MENU_NAME: Reownership" \ - --menu "Greenwich Mean Time (GMT) : $date\nTOTP: $TOTP | HOTP: $HOTP | HASHES: $HASH" 20 90 10 \ + --menu "Greenwich Mean Time (GMT) : $date\nTOTP: $TOTP | HOTP: $HOTP | /BOOT INTEGRITY: $HASH" 20 90 10 \ 'C' ' Continue ownership of devices' \ 'x' ' Exit to recovery shell' \ 2>/tmp/whiptail || recovery "GUI menu failed" @@ -256,6 +256,7 @@ while true; do --menu "Select A Boot Option" 20 90 10 \ 'm' ' Show OS boot menu' \ 'u' ' USB boot' \ + 'z' ' SDCARD boot' \ 'i' ' Ignore tampering and force a boot (Unsafe!)' \ 'r' ' <-- Return to main menu' \ 2>/tmp/whiptail || recovery "GUI menu failed" @@ -302,6 +303,13 @@ while true; do continue fi + if [ "$totp_confirm" = "z" ]; then + mount-sdcard + exec /bin/usb-init + continue + fi + + if [ "$totp_confirm" = "g" ]; then if (whiptail --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?" 16 90) then diff --git a/initrd/bin/kexec-seal-key b/initrd/bin/kexec-seal-key index 880f10b54..b422a7720 100755 --- a/initrd/bin/kexec-seal-key +++ b/initrd/bin/kexec-seal-key @@ -98,8 +98,8 @@ cat "$KEY_DEVICES" | cut -d\ -f1 | xargs /bin/qubes-measure-luks \ || die "Unable to measure the LUKS headers" luks_pcr=`tpm calcfuturepcr -ix 16 -if /tmp/luksDump.txt` -# Librem Key/Nitrokey loads USB modules which changes PCR5. -# In the event Librem Key/Nitrokey is enabled, skip verification of PCR5 +# Librem Key loads USB modules which changes PCR5. +# In the event Librem Key is enabled, skip verification of PCR5 if [ -x /bin/libremkey_hotp_verification ]; then pcr_5="X" else diff --git a/initrd/bin/reencrypt-luks b/initrd/bin/reencrypt-luks index 63f30c1d8..f756fad29 100755 --- a/initrd/bin/reencrypt-luks +++ b/initrd/bin/reencrypt-luks @@ -57,7 +57,7 @@ if [ -n "$reownership_state" ] && [ "$reownership_state" = "luks_reencryption" ] #Validate past cryptsetup attempts if [ $(echo $?) -ne 0 ]; then whiptail --title 'Invalid Actual LUKS Disk Recovery Key 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.\n\nTo do so, place ISO file and its 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 an external drive.\n\nTo do so, place ISO file and its signature file on root of external drive,\n and select Settings-> Boot from \n\nHit Enter to continue." 30 60 shred -n 10 -z -u /tmp/oem_luks_actual_Disk_Recovery_Key 2> /dev/null #unsetting oem_luks_actual_Disk_Recovery_Key will prompt user for Disk Recovery Key passphrase prompt on next round unset oem_luks_actual_Disk_Recovery_Key diff --git a/initrd/bin/seal-libremkey b/initrd/bin/seal-libremkey index 381273109..fe5d2442f 100755 --- a/initrd/bin/seal-libremkey +++ b/initrd/bin/seal-libremkey @@ -1,5 +1,5 @@ #!/bin/sh -# Retrieve the sealed TOTP secret and initialize a Librem Key/NitroKey with it +# Retrieve the sealed TOTP secret and initialize a Librem Key with it . /etc/functions @@ -52,14 +52,14 @@ counter_value=1 enable_usb if ! libremkey_hotp_verification info ; then - echo "Insert your Librem Key/NitroKey and press Enter to configure it" + echo "Insert your Librem Key and press Enter to configure it" read libremkey_hotp_verification info \ - || die "Unable to find Librem Key/NitroKey" + || die "Unable to find Librem Key" fi if [ -z "$oem_gpg_Admin_PIN" ]; then - read -s -p "Enter your Librem Key/NitroKey Admin PIN:" admin_pin + read -s -p "Enter your Librem Key Admin PIN:" admin_pin echo else admin_pin=$(echo -n "$oem_gpg_Admin_PIN") @@ -91,7 +91,7 @@ echo "$counter_value" > $HOTP_COUNTER \ #|| die "Unable to create HOTP counter file" mount -o remount,ro /boot -echo "Librem Key/NitroKey initialized successfully. Press Enter to continue." +echo "Librem Key initialized successfully. Press Enter to continue." read exit 0 diff --git a/initrd/etc/functions b/initrd/etc/functions index da17af759..2f3846179 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -329,7 +329,8 @@ read_oem_files() if ! [ $(grep "no_automatic_provisioning" /boot/oem) ]; then echo "Mounting memory card reader drive provision OEM reownership from /media/oem-provisioning..." - mount-sdcard || recovery "Unable to mount sdcard from memory card reader. Make sure the card is pushed in and type 'reboot' to continue." + mount-sdcard || notify "Unable to mount sdcard from memory card reader. Make sure the card is pushed in the expension slot and type Enter to continue." + mount-sdcard || $(mount -o remount,rw /boot && echo "no_automatic_provisioning" >> /boot/oem && mount -o remount,ro /boot && reboot) if [ -e /media/oem-provisioning ]; then echo "Found /media/oem-provisioning. Parsing..." oem_gpg_Admin_PIN=$(grep "^oem_gpg_Admin_PIN=" /media/oem-provisioning | cut -d "=" -f2) @@ -492,14 +493,14 @@ read_oem_files() clear echo "$to_provision: GPG Admin PIN" echo - echo "Here chosen GPG Admin PIN will be requested from you under Heads to visually attest integrity measurements on NitroKey/Librem Key (HOTP)." - echo "Outside of Heads, your GPG Admin PIN will be prompted from you to manage your Nitrokey/Librem Key. (e.g: Change user PIN.)" + echo "Here chosen GPG Admin PIN will be requested from you under Heads to visually attest integrity measurements on your Librem Key (HOTP)." + echo "Outside of Heads, your GPG Admin PIN will be prompted from you to manage your Librem Key. (e.g: Change user PIN.)" echo "IMPORTANT: GPG Admin PIN is required to unlock GPG User PIN locked from 3 consecutive bad User PINs." echo "If you mistyped your GPG Admin PIN 2 times in a subsequently, MAKE SURE YOUR THIRD ATTEMPT IS VALID by checking oem-provisioning file, created from this Wizard on OEM provided sdcard's encrypted container." echo echo "IMPORTANT: If the GPG Admin PIN becomes locked in smartcard THE CARD WILL NEED TO BE FACTORY RESETTED!" echo "Factory reset of the GPG card deletes everything on it, including your private keys stored in its embedded GPG smartcard." - echo "Consequently, you won't be able to decrypt previous files and emails with your Nitrokey/Librem Key like prior to the reset." + echo "Consequently, you won't be able to decrypt previous files and emails with your Librem Key like prior to the reset." echo echo "There is no need to have a super strong passphrase here, it will be locked after 3 bad attempts in the GPG smartcard itself." echo "Better choose a simple, short passphrase that you'll remember forever then one long that would lock yourself off because forgotten." @@ -578,7 +579,6 @@ read_oem_files() done notify "oem_luks_actual_Disk_Recovery_Key=$passphrase" export oem_luks_actual_Disk_Recovery_Key="$passphrase" - #TODO: actual should be replaced by new LUKS recovery key after reencryption. fi if [ "$to_provision" == "oem_luks_new_Disk_Recovery_Key" ]; then clear @@ -589,7 +589,6 @@ read_oem_files() echo echo "If forgotten, the content of both $oem_name shipped microsd disk and computer internal disk will be lost forever." echo "It is suggested that you pick a diceware passphrase of 6+ words. Make something emotionnaly involving from those words." - #TODO replicate this with validation randomize_diceware_passphrases_until_chosen_or_manual 6 UpperFirstLetter Nospace while [[ ${#passphrase} -lt 25 ]]; do echo "We impose a minimal requirement of 25 characters for LUKS Disk Recovery Passphrase." @@ -664,9 +663,9 @@ check_onboarding_progress() if [ $? -ne 0 ];then #Show Onboarding menu once. whiptail --title 'Hardware reownership Wizard' --msgbox \ - "The received hardware is currently owned by $oem_name.\nWe will change that.\n\nThis Wizard will otherwise make you own your own hardware by:\n1-Reencrypting encrypted drives content (LUKS containers)\n2-Changing their LUKS Disk Recovery Keys and their passphrases\n3-Resetting your Librem Key/Nitrokey Pro v2 to factory defaults\n4-Setting User and Admin PINs into your Librem Key/NitroKey\n5-Generating keys into its smartcard, exporting public key and\n importing it in the ROM prior to reprogramming the SPI flash with it\n6-Taking integrity measures of all /boot files and sign the resulting\n checksum file with your Librem Key/Nitrokey Pro\n7-Reowning your Trusted Platform Module (TPM)\n\nScan the QR Code with an OTP app only after Reset the TPM last phase.\n\nHit Enter to continue." 20 20 + "The received hardware is currently owned by $oem_name.\nWe will change that.\n\nThis Wizard will otherwise make you own your own hardware by:\n1-Reencrypting encrypted drives content (LUKS containers)\n2-Changing their LUKS Disk Recovery Keys and their passphrases\n3-Resetting your Librem Key to factory defaults\n4-Setting User and Admin PINs into your Librem Key\n5-Generating keys into its smartcard, exporting public key and\n importing it in the ROM prior to reprogramming the SPI flash with it\n6-Taking integrity measures of all /boot files and sign the resulting\n checksum file with your Librem Key\n7-Reowning your Trusted Platform Module (TPM)\n\nScan the QR Code with an OTP app only after Reset the TPM last phase.\n\nHit Enter to continue." 20 20 whiptail --title 'Hardware reownership Wizard' --msgbox \ - "On the next screen, MAKE SURE THAT THE HOTP CODE IS: 'Success'\n\nIf it's not, reboot your hardware with your Librem/Nitrokey inserted.\n\nIf the HOTP code is still invalid, your hardware may been tampered with in\ntransit. Contact $oem_name." 20 20 + "On the next screen, MAKE SURE THAT THE HOTP CODE IS: 'Success'\n\nIf it's not, reboot your hardware with your Librem Key inserted.\n\nIf the HOTP code is still invalid, your hardware may been tampered with in\ntransit. Contact $oem_name." 20 20 totp_confirm="O" echo $totp_confirm > /tmp/whiptail mount -o remount,rw /boot @@ -688,7 +687,7 @@ check_onboarding_progress() fi res=$(grep gpg_factory_resetted /boot/oem > /dev/null 2>&1) if [ $? -ne 0 ];then - /bin/factory-reset-nitrokey-libremkey.sh + /bin/factory-reset-libremkey.sh return fi res=$(grep tpm_reowned /boot/oem > /dev/null 2>&1) @@ -706,13 +705,13 @@ check_onboarding_progress() unset reownership_state if [ "$CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY" = "y" ]; then whiptail --title 'DISK UNLOCK KEY ADVICE 1/3' --msgbox \ - "***You SHOULD SET a new Disk Unlock Key for your own data privacy!!!***\n\nDoing so, a witness will only be able to type observed Disk Unlock\n Key passphrase from this computer and won't be able on a cloned\n copy of this disk.\n\nThe release of Disk Unlock Key happens ONLY if TPM attests firmware\nintegrity, and only if Disk Unlock Key passphrase is valid.\n\nPlease hit Enter to continue" 30 60 + "***You SHOULD SET a new Disk Unlock Key for your own data privacy!!!***\n\nDoing so, a witness will only be able to type observed Disk Unlock\n Key passphrase on this computer and won't be able on a cloned\n copy of this disk.\n\nThe release of Disk Unlock Key happens ONLY if TPM attests firmware\nintegrity, and only if Disk Unlock Key passphrase is valid.\n\nPlease hit Enter to continue" 30 60 whiptail --title 'DISK UNLOCK KEY ADVICE 2/3' --msgbox \ "Otherwise, typing your Disk Recovery Key passphrase at boot puts you\nat risk. Someone could clone your disk and type that witnessed\npassphrase and access your data both locally and from a cloned\ndisk.\n\nCoupled with a strong passphrase, this improves your data privacy.\nCONSIDER YOURSELF WARNED.\n\nPlease hit Enter to continue" 30 60 whiptail --title 'DISK UNLOCK KEY ADVICE 3/3' --msgbox \ - "To set Disk Unlock Key, released by the TPM only if firmware integrity\n is attested:\n\nSelect from Main menu:\n\nAdvanced Options menu -> Other Boot Options -> Show OS boot menu\n1-Then select the first boot option proposed (dynamic option)\n2-Then,answer Y when asked to add Disk Unlock Key to the TPM.\n\nYou will be prompted to set one in the following steps.\n\nPlease hit Enter to continue" 30 60 + "To set Disk Unlock Key, released by the TPM only if firmware integrity\n is attested:\n\nSelect from Main menu:\n\nSettings -> Other Boot Options -> Show OS boot menu\n1-Then select the first boot option proposed (dynamic option)\n2-Then,answer Y when asked to add Disk Unlock Key to the TPM.\n\nYou will be prompted to set one in the following steps.\n\nPlease hit Enter to continue" 30 60 fi return else @@ -744,7 +743,7 @@ reset_disk_unlock_key() HOTP=`unseal-hotp` enable_usb if ! libremkey_hotp_verification info ; then - whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'WARNING: Please Insert Your Librem Key/Nitrokey' --msgbox "Your Librem Key/Nitrokey was not detected.\n\nPlease insert your Librem Key/Nitrokey" 30 90 + whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'WARNING: Please Insert Your Librem Key' --msgbox "Your Librem Key was not detected.\n\nPlease insert your Librem Key" 30 90 fi # Don't output HOTP codes to screen, so as to make replay attacks harder libremkey_hotp_verification check "$HOTP" @@ -757,7 +756,7 @@ reset_disk_unlock_key() MAIN_MENU_BG_COLOR=$CONFIG_ERROR_BG_COLOR ;; * ) - HOTP="Error checking code, Insert Librem Key/Nitrokey and retry" + HOTP="Error checking code, Insert Librem Key and retry" MAIN_MENU_BG_COLOR=$CONFIG_WARNING_BG_COLOR ;; esac From c5946acae9a05929343354812335f4dc1cb2c403 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Tue, 11 Jun 2019 14:30:42 -0400 Subject: [PATCH 68/91] Change x230 OEM default board build to x230-libremkey --- .gitlab-ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c715ab191..fea1a1d2e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -15,14 +15,14 @@ build: key: "$CI_COMMIT_REF_SLUG" script: - make BOARD=x230-flash - - make BOARD=x230 + - make BOARD=x230-libremkey - echo "x230-flash hashes:" - cat ./build/x230-flash/hashes.txt - echo "x230 hashes:" - - cat ./build/x230/hashes.txt + - cat ./build/x230-libremkey/hashes.txt artifacts: paths: - ./build/x230-flash/x230-flash.rom - ./build/x230-flash/hashes.txt - - ./build/x230/coreboot.rom - - ./build/x230/hashes.txt + - ./build/x230-libremkey/coreboot.rom + - ./build/x230-libremkey/hashes.txt From bf5761bacd3dee7cedeccb55f35edeffb031e15c Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Wed, 12 Jun 2019 13:05:56 -0400 Subject: [PATCH 69/91] x230-libremkey missed requirements --- boards/x230-libremkey/x230-libremkey.config | 4 +- config/coreboot-x230-libremkey.config | 24 ++ config/linux-x230-libremkey.config | 321 ++++++++++++++++++++ 3 files changed, 347 insertions(+), 2 deletions(-) create mode 100644 config/coreboot-x230-libremkey.config create mode 100644 config/linux-x230-libremkey.config diff --git a/boards/x230-libremkey/x230-libremkey.config b/boards/x230-libremkey/x230-libremkey.config index 11f14eae4..b9493ecce 100644 --- a/boards/x230-libremkey/x230-libremkey.config +++ b/boards/x230-libremkey/x230-libremkey.config @@ -1,7 +1,7 @@ # Configuration for a x230 with Librem Key, running Qubes and other OSes export CONFIG_COREBOOT=y -CONFIG_COREBOOT_CONFIG=config/coreboot-x230.config -CONFIG_LINUX_CONFIG=config/linux-x230.config +CONFIG_COREBOOT_CONFIG=config/coreboot-x230-libremkey.config +CONFIG_LINUX_CONFIG=config/linux-x230-libremkey.config CONFIG_CRYPTSETUP=y CONFIG_FLASHROM=y diff --git a/config/coreboot-x230-libremkey.config b/config/coreboot-x230-libremkey.config new file mode 100644 index 000000000..8a95196be --- /dev/null +++ b/config/coreboot-x230-libremkey.config @@ -0,0 +1,24 @@ +CONFIG_LOCALVERSION="heads" +# CONFIG_INCLUDE_CONFIG_FILE is not set +# CONFIG_COLLECT_TIMESTAMPS is not set +CONFIG_USE_BLOBS=y +CONFIG_MEASURED_BOOT=y +CONFIG_VENDOR_LENOVO=y +CONFIG_CBFS_SIZE=0x700000 +# CONFIG_POST_IO is not set +# CONFIG_POST_DEVICE is not set +CONFIG_DRIVERS_UART_8250IO=y +CONFIG_BOARD_LENOVO_X230=y +CONFIG_DRIVERS_PS2_KEYBOARD=y +CONFIG_UART_PCI_ADDR=0 +CONFIG_NO_GFX_INIT=y +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_CONSOLE_CBMEM_BUFFER_SIZE=0x80000 +CONFIG_DEFAULT_CONSOLE_LOGLEVEL_5=y +CONFIG_PAYLOAD_LINUX=y +CONFIG_PAYLOAD_FILE="../../build/x230-libremkey/bzImage" +CONFIG_PAYLOAD_OPTIONS="" +# CONFIG_PXE is not set +CONFIG_LINUX_COMMAND_LINE="intel_iommu=igfx_off quiet loglevel=3" +CONFIG_LINUX_INITRD="../../build/x230-libremkey/initrd.cpio.xz" +CONFIG_DEBUG_SMM_RELOCATION=y diff --git a/config/linux-x230-libremkey.config b/config/linux-x230-libremkey.config new file mode 100644 index 000000000..bc8544c07 --- /dev/null +++ b/config/linux-x230-libremkey.config @@ -0,0 +1,321 @@ +CONFIG_LOCALVERSION="-heads" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_KERNEL_XZ=y +# CONFIG_SWAP is not set +# CONFIG_CROSS_MEMORY_ATTACH is not set +# CONFIG_FHANDLE is not set +CONFIG_NO_HZ_IDLE=y +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="../../../blobs/dev.cpio" +# CONFIG_RD_GZIP is not set +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_LZ4 is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_SGETMASK_SYSCALL is not set +# CONFIG_SYSFS_SYSCALL is not set +# CONFIG_BASE_FULL is not set +# CONFIG_SIGNALFD is not set +# CONFIG_TIMERFD is not set +# CONFIG_EVENTFD is not set +# CONFIG_AIO is not set +# CONFIG_ADVISE_SYSCALLS is not set +# CONFIG_MEMBARRIER is not set +CONFIG_EMBEDDED=y +# CONFIG_VM_EVENT_COUNTERS is not set +# CONFIG_SLUB_DEBUG is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_JUMP_LABEL=y +CONFIG_CC_STACKPROTECTOR_STRONG=y +CONFIG_MODULES=y +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_SMP=y +# CONFIG_X86_EXTENDED_PLATFORM is not set +CONFIG_PROCESSOR_SELECT=y +# CONFIG_CPU_SUP_CENTAUR is not set +CONFIG_PREEMPT_VOLUNTARY=y +CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y +# CONFIG_X86_MCE_AMD is not set +# CONFIG_PERF_EVENTS_INTEL_RAPL is not set +# CONFIG_MICROCODE is not set +# CONFIG_SPARSEMEM_VMEMMAP is not set +# CONFIG_COMPACTION is not set +# CONFIG_BOUNCE is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 +CONFIG_X86_PMEM_LEGACY=y +# CONFIG_MTRR is not set +# CONFIG_X86_SMAP is not set +# CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS is not set +# CONFIG_SECCOMP is not set +CONFIG_KEXEC=y +CONFIG_KEXEC_FILE=y +# CONFIG_RELOCATABLE is not set +CONFIG_PHYSICAL_ALIGN=0x1000000 +# CONFIG_MODIFY_LDT_SYSCALL is not set +# CONFIG_SUSPEND is not set +CONFIG_PCI_MSI=y +# CONFIG_HT_IRQ is not set +CONFIG_PCI_IOV=y +CONFIG_PCI_PRI=y +# CONFIG_COREDUMP is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_SYN_COOKIES=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_DIAG is not set +# CONFIG_IPV6 is not set +# CONFIG_WIRELESS is not set +# CONFIG_UEVENT_HELPER is not set +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_STANDALONE is not set +# CONFIG_FIRMWARE_IN_KERNEL is not set +# CONFIG_ALLOW_DEV_COREDUMP is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=65536 +CONFIG_EEPROM_93CX6=m +CONFIG_INTEL_MEI_ME=m +CONFIG_INTEL_MEI_TXE=m +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_DEV_SR=y +CONFIG_CHR_DEV_SG=y +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_ISCSI_TCP=y +CONFIG_ATA=y +CONFIG_SATA_AHCI=y +# CONFIG_ATA_SFF is not set +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_NETDEVICES=y +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NET_VENDOR_ADAPTEC is not set +# CONFIG_NET_VENDOR_AGERE is not set +# CONFIG_NET_VENDOR_ALTEON is not set +# CONFIG_NET_VENDOR_AMAZON is not set +# CONFIG_NET_VENDOR_AMD is not set +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_VENDOR_ATHEROS is not set +# CONFIG_NET_CADENCE is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_BROCADE is not set +# CONFIG_NET_VENDOR_CAVIUM is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_NET_VENDOR_CISCO is not set +# CONFIG_NET_VENDOR_DEC is not set +# CONFIG_NET_VENDOR_DLINK is not set +# CONFIG_NET_VENDOR_EMULEX is not set +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_EXAR is not set +# CONFIG_NET_VENDOR_HP is not set +CONFIG_E1000=m +CONFIG_E1000E=m +# CONFIG_NET_VENDOR_I825XX is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MELLANOX is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MYRI is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETRONOME is not set +# CONFIG_NET_VENDOR_NVIDIA is not set +# CONFIG_NET_VENDOR_OKI is not set +# CONFIG_NET_PACKET_ENGINE is not set +# CONFIG_NET_VENDOR_QLOGIC is not set +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_REALTEK is not set +# CONFIG_NET_VENDOR_RENESAS is not set +# CONFIG_NET_VENDOR_RDC is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SILAN is not set +# CONFIG_NET_VENDOR_SIS is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SUN is not set +# CONFIG_NET_VENDOR_TEHUTI is not set +# CONFIG_NET_VENDOR_TI is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_NET_VENDOR_SYNOPSYS is not set +# CONFIG_USB_NET_DRIVERS is not set +# CONFIG_WLAN is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_SERIO_SERPORT is not set +# CONFIG_UNIX98_PTYS is not set +# CONFIG_LEGACY_PTYS is not set +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +# CONFIG_SERIAL_8250_PNP is not set +# CONFIG_SERIAL_8250_PCI is not set +# CONFIG_SERIAL_8250_LPSS is not set +# CONFIG_SERIAL_8250_MID is not set +CONFIG_TTY_PRINTK=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_TIMERIOMEM=m +CONFIG_HW_RANDOM_INTEL=m +CONFIG_HW_RANDOM_AMD=m +CONFIG_HW_RANDOM_VIA=m +CONFIG_HW_RANDOM_TPM=m +CONFIG_TCG_TPM=y +CONFIG_TCG_TIS=y +# CONFIG_I2C_COMPAT is not set +CONFIG_I2C_MUX=m +CONFIG_I2C_MUX_PCA9541=m +CONFIG_I2C_MUX_REG=m +# CONFIG_I2C_HELPER_AUTO is not set +CONFIG_I2C_SLAVE=y +CONFIG_PTP_1588_CLOCK=y +# CONFIG_HWMON is not set +# CONFIG_X86_PKG_TEMP_THERMAL is not set +CONFIG_MFD_SYSCON=y +CONFIG_DRM=y +CONFIG_DRM_I915=y +CONFIG_FB_VESA=y +# CONFIG_LCD_CLASS_DEVICE is not set +# CONFIG_BACKLIGHT_GENERIC is not set +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_USB=y +CONFIG_USB_XHCI_HCD=m +CONFIG_USB_XHCI_PLATFORM=m +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_HCD_PLATFORM=m +CONFIG_USB_STORAGE=m +CONFIG_MMC=m +CONFIG_MMC_SDHCI=m +CONFIG_MMC_SDHCI_PCI=m +CONFIG_RTC_CLASS=y +# CONFIG_X86_PLATFORM_DEVICES is not set +CONFIG_INTEL_IOMMU=y +CONFIG_INTEL_IOMMU_SVM=y +CONFIG_GENERIC_PHY=y +# CONFIG_BLK_DEV_PMEM is not set +# CONFIG_ND_BLK is not set +# CONFIG_BTT is not set +# CONFIG_FIRMWARE_MEMMAP is not set +# CONFIG_DMIID is not set +CONFIG_GOOGLE_FIRMWARE=y +CONFIG_GOOGLE_MEMCONSOLE_X86_LEGACY=y +# CONFIG_EXT2_FS is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_USE_FOR_EXT2=y +# CONFIG_DNOTIFY is not set +# CONFIG_INOTIFY_USER is not set +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +# CONFIG_PROC_SYSCTL is not set +# CONFIG_PROC_PAGE_MONITOR is not set +# CONFIG_MISC_FILESYSTEMS is not set +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_UTF8=y +CONFIG_PRINTK_TIME=y +CONFIG_BOOT_PRINTK_DELAY=y +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_HARDLOCKUP_DETECTOR=y +CONFIG_WQ_WATCHDOG=y +# CONFIG_SCHED_DEBUG is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_FTRACE is not set +# CONFIG_STRICT_DEVMEM is not set +# CONFIG_X86_VERBOSE_BOOTUP is not set +# CONFIG_DOUBLEFAULT is not set +CONFIG_IO_DELAY_0XED=y +CONFIG_OPTIMIZE_INLINING=y +# CONFIG_X86_DEBUG_FPU is not set +CONFIG_HARDENED_USERCOPY=y +CONFIG_CRYPTO_RSA=m +CONFIG_CRYPTO_USER=y +CONFIG_CRYPTO_MCRYPTD=m +CONFIG_CRYPTO_AUTHENC=m +CONFIG_CRYPTO_CCM=m +CONFIG_CRYPTO_GCM=m +CONFIG_CRYPTO_CHACHA20POLY1305=m +CONFIG_CRYPTO_CTS=m +CONFIG_CRYPTO_LRW=y +CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_XTS=y +CONFIG_CRYPTO_KEYWRAP=m +CONFIG_CRYPTO_CMAC=m +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_VMAC=m +CONFIG_CRYPTO_CRC32C_INTEL=y +CONFIG_CRYPTO_CRC32=m +CONFIG_CRYPTO_CRC32_PCLMUL=m +CONFIG_CRYPTO_CRCT10DIF_PCLMUL=m +CONFIG_CRYPTO_POLY1305_X86_64=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_RMD128=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_RMD256=m +CONFIG_CRYPTO_RMD320=m +CONFIG_CRYPTO_SHA1_SSSE3=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m +CONFIG_CRYPTO_AES_NI_INTEL=y +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_BLOWFISH_X86_64=m +CONFIG_CRYPTO_CAMELLIA=m +CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64=m +CONFIG_CRYPTO_CAST5_AVX_X86_64=m +CONFIG_CRYPTO_CAST6_AVX_X86_64=m +CONFIG_CRYPTO_DES3_EDE_X86_64=m +CONFIG_CRYPTO_FCRYPT=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_SALSA20=m +CONFIG_CRYPTO_CHACHA20_X86_64=m +CONFIG_CRYPTO_SEED=m +CONFIG_CRYPTO_SERPENT_SSE2_X86_64=m +CONFIG_CRYPTO_SERPENT_AVX2_X86_64=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_TWOFISH_AVX_X86_64=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_842=m +CONFIG_CRYPTO_LZ4=m +CONFIG_CRYPTO_LZ4HC=m +CONFIG_CRYPTO_ANSI_CPRNG=m +CONFIG_CRYPTO_DRBG_HASH=y +CONFIG_CRYPTO_DRBG_CTR=y +CONFIG_CRYPTO_USER_API_HASH=y +CONFIG_CRYPTO_USER_API_SKCIPHER=y +CONFIG_CRYPTO_USER_API_RNG=y +CONFIG_CRYPTO_USER_API_AEAD=y +# CONFIG_CRYPTO_HW is not set +# CONFIG_VIRTUALIZATION is not set +CONFIG_CRC_CCITT=m +CONFIG_CRC_T10DIF=y +CONFIG_CRC_ITU_T=m +CONFIG_CRC7=m +CONFIG_LIBCRC32C=m +CONFIG_CRC8=m +CONFIG_XZ_DEC_TEST=m +CONFIG_CORDIC=m +CONFIG_IRQ_POLL=y From 9a65931c5707d868a3a14da65e20017646636e8a Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Wed, 12 Jun 2019 13:11:01 -0400 Subject: [PATCH 70/91] Fix USB boot following mount-usb changes deprecating CONFIG_USB_BOOT_DEV usage --- initrd/bin/usb-scan | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/initrd/bin/usb-scan b/initrd/bin/usb-scan index 6d3eda27d..4b023c513 100755 --- a/initrd/bin/usb-scan +++ b/initrd/bin/usb-scan @@ -12,7 +12,7 @@ fi # Mount the USB boot device if ! grep -q /media /proc/mounts ; then - mount-usb "$CONFIG_USB_BOOT_DEV" \ + mount-usb \ || die "Unable to mount /media" fi @@ -72,7 +72,7 @@ if [ `cat /tmp/iso_menu.txt | wc -l` -gt 0 ]; then if [ -n "$option" ]; then MOUNTED_ISO=$option ISO=${option:7} # remove /media/ to get device relative path - kexec-iso-init $MOUNTED_ISO $ISO $CONFIG_USB_BOOT_DEV + kexec-iso-init $MOUNTED_ISO $ISO $(grep "/media" /proc/mounts | awk -F " " '{print $1}') die "Something failed in iso init" fi From b884994a14ba878424071aec106d6f41c842f565 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Wed, 12 Jun 2019 17:31:00 -0400 Subject: [PATCH 71/91] Playing with gitlab caches... Still some corruption found. Grrrr... --- .gitlab-ci.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fea1a1d2e..e34cc416b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,10 +5,11 @@ stages: build: stage: build - cache: - untracked: true - paths: - - ./git + #This doesn't work.... For some reason, current gitlab has cached version of initrd/bin/gui-init for which sha256sum is fb989c27e035c20cb04df9f01696aa5d585d2e79d826cc740d169545b6de3f42 when local git is 4d4e3ad88cae723094eafbc66d2266e65d70cee8f660d52602ddbb8ee0283838... I don't get those corruptions. + #cache: + # untracked: true + # paths: + # - ./git cache: paths: - ./ From 00b4d87623d785919fdb314d462261999237db8a Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Wed, 12 Jun 2019 20:58:59 -0400 Subject: [PATCH 72/91] Try to cache only the .build dir --- .gitlab-ci.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e34cc416b..7274d629e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,14 +5,9 @@ stages: build: stage: build - #This doesn't work.... For some reason, current gitlab has cached version of initrd/bin/gui-init for which sha256sum is fb989c27e035c20cb04df9f01696aa5d585d2e79d826cc740d169545b6de3f42 when local git is 4d4e3ad88cae723094eafbc66d2266e65d70cee8f660d52602ddbb8ee0283838... I don't get those corruptions. - #cache: - # untracked: true - # paths: - # - ./git cache: paths: - - ./ + - ./build key: "$CI_COMMIT_REF_SLUG" script: - make BOARD=x230-flash From c20c1842594eeefbb1da831f9de75bbd0ef119d7 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Thu, 13 Jun 2019 14:08:06 -0400 Subject: [PATCH 73/91] Documentation changes --- initrd/.ash_history | 4 +- oem-reownership/oem-provisioning.example | 80 ++++++++++++++++-------- oem-reownership/oem.example | 15 ++++- 3 files changed, 70 insertions(+), 29 deletions(-) diff --git a/initrd/.ash_history b/initrd/.ash_history index e6f5303e0..639bfdb5b 100644 --- a/initrd/.ash_history +++ b/initrd/.ash_history @@ -1,5 +1,5 @@ -#To activate OEM reownership wizard, under Heads recovery console, do: -mount /boot||true && mount -o remount,rw /boot && echo "oem_name=COMPANY NAME" > /boot/oem && mount -o remount,ro /boot && reboot +#To activate OEM reownership wizard, once testing OS boot with Disk Unlock Key passphrase,insert prepared sdcard in memory expension slot and do: +mount-sdcard && mount -o remount,rw /media && touch /media/oem-provisioning && mount -o remount,ro /media && mount /boot||true && mount -o remount,rw /boot && echo "oem_name=COMPANY NAME" > /boot/oem && echo "oem_provisioning_partition=/dev/mmcblk0p1" >> /boot/oem && mount -o remount,ro /boot && reboot #remove invalid kexec.sig signed checksum file mount /boot||true && mount -o remount,rw /boot && rm /boot/kexec.sig && mount -o remount,ro /boot #Generate keys from GPG smartcard: diff --git a/oem-reownership/oem-provisioning.example b/oem-reownership/oem-provisioning.example index ab68b7e7e..53141a414 100644 --- a/oem-reownership/oem-provisioning.example +++ b/oem-reownership/oem-provisioning.example @@ -1,6 +1,29 @@ ########### # OEM # ########### +# Requirements +# - Stable, OEM ReOwnership branch of Heads (should be streamlines soon) is flashed. +# - (Recommended) Intel ME is neutered per Heads wiki instructions (TODO: PUT HERE) +# +# - OS is preinstalled under LUKS container. (QubesOS recommended) +# - Heads /boot files checksum digest file (/boot/kexec_hashes.txt) is signed (/boot/kexec.sig) +# and boot integrity is validated by OEM's public key already present in rom. +# The OEM is encouraged to use the OEM wizard himself to randomly generate strong passphrases. +# - TPMTOTP/HOTP is already sealed +# - (Recommended) A Disk Unlock Key is set, which partition is defined under /boot/kexec_key_devices.txt) +# - Otherwise, the OEM wizard will prompt the user at Disk Unlock Key to choose between /dev/sda2 and /dev/mmcblk0p2 +# - A prepared sdcard with a LUKS container containing an ext4 partition of ~32Mb is required +# The encryption passphrase is REQUIRED TO BE THE SAME OF THE OS DISK INSTALLATION (Named: actual Recovery Key passphrase) +# A 16Gb sdcard, with a second partition containing QubesOS latest iso and signature file is recommended. +# +# The OEM is advised to use the OEM Wizard himself after having cloned its OEM OS installation onto internal SSD drive. +# The OEM having completed OEM reownership should be able to boot OS with Disk Unlock Key, +# for which Heads validates all prior steps automatically, including the sdcard reencryption, which could fail on cheap +# flash memory. +# Having done so, from Heads recovery: +# The OEM inserts preformated sdcard in ssdcard memory expension slot then: +# "mount-sdcard rw" and then "touch /media/oem-provisioning" and "umount /media" +# # To activate OEM reownership wizard, under Heads recovery console, do: # mount /boot # mount -o remount,rw /boot @@ -9,27 +32,27 @@ # reboot # # To activate OEM automatic provisioning, the content of this file needs to be found by Heads under: -# /media/oem-provisioning -# By default, the USB drive is mounted from /dev/sdb1 but "mount-usb" will find the usb drive and mount it under /media +# /media/oem-provisioning by calling "mount-sdcard" # -# Replace variables content with your own! -# +# Replace variables content with your own manually, or provide a blank or partial file, the OEM Reownership Wizard will take care of the rest! +# BE CONSCIOUS THAT MANUALLY ENTERED VALUES HERE WON'T BE VALIDATED BUT LATER IN THE OEM PROCESS (mainly GPG related ones wich could cause problem). #The following needs to be put in /boot/oem for OEM name to be shown at OEM Reownership wizard first screen. Else it is going to be "your OEM". #oem_name=Insurgo Open Technologies # #On a recovery shell, type the UP arrow key until you reach top of the history buffer. A command is proposed for you to change "YOUR COMPANY" # to your own. The hardware is then ready to ship and the wizard will accompany the user in reowning the hardware and OEM secrets on next reboot. # -# You should invite the user into using "generate_diceware-eom-provisioning.sh" script in the current directory, -# which uses diceware to prefeed "oem-provisioning.generated" with proper secrets. -# The user would then need to put that file under "oem-provisioning" on the root of a dedicated USB drive and connect on first boot of -# received hardware to reduce user errors and friction of having to enter those secrets manually. +# A manual script "generate_diceware-eom-provisioning.sh" is provided in the current directory, but OEM ReOwnership itself is recommended. +# It uses install diceware (in your disto repositories) to prefeed "oem-provisioning.generated" with proper secrets. +# The user would then need to put that file under "oem-provisioning" on the root of a dedicated sdcard LUKS contained ext4 partition +# and insert it on first boot. Not having that sdcard in place nor oem-provisioning file will result in "no_automatic_provisioning" +# appended in /boot/oem and will force the OEM ReOwnership Wizard to request the user to enter all informatio nmanually through the process. ######### # GPG # ######### # GPG card function in Heads: -# The Librem Key/NitroKey is a traditional GPG card added with HMAC-based One-time Password (HOTP) which permits +# The Librem Key/NitroKey Pro is a traditional GPG card added with HMAC-based One-time Password (HOTP) which permits # to seal integrity measurements into the GPG card memory. # # As a functional result, at each boot, the card will flash its LED green if the measured boot integrity @@ -45,10 +68,10 @@ # # *** You should use both TOTP/HOTP so you can still validate attested integiryt in case your GPG card gets lost *** # -# HOTP/TOTP are functionally similar, while the Librem Key/Nitrokey permits to validate integrity visually in an +# HOTP/TOTP are functionally similar, while the Librem Key/Nitrokey Pro permits to validate integrity visually in an # instant without having to unlock the smartphone, open the OTP application and verify that a 6 digits code there # is the same that is shown on the screen. -# HOTP Librem Key/Nitrokey feature is complementory to the TOTP and shares the same codebase. +# HOTP Librem Key / Nitrokey Pro/Storage feature is complementory to the TOTP and shares the same codebase. # # Heads also depends on the GPG card to store used private key outside of prying eyes, securely stored on the # Smartcard. When factory resetting the card, only the public key is inserted into the rom, which is used @@ -90,7 +113,7 @@ # #GPG SmartCard desired Admin PIN to provision GPG factory reset. # Admin PIN manages Admin functions of the card through gpg --edit-card admin functions, -# In Heads, the Admin PIN is required to seal HOTP secret into NitroKey/Librem Key when firmware has been modified. +# In Heads, the Admin PIN is required to seal HOTP secret into NitroKey Pro/Librem Key when firmware has been modified. # # NOTES: If the GPG card is lost, the user won't be able to seal firmware changes through HOTP. # Size constaints: minimum 8 characters, maximum 20 characters, WITHOUT SPACES! @@ -115,7 +138,7 @@ oem_gpg_User_PIN=Insurgo # This will be used to construct the ID of the public key: "Real Name (Comment) email@address.org" # # Size constaints: minimum 5 characters. -oem_gpg_real_name=Insurgo Integrity Delivered Attestation Attestation Librem Key +oem_gpg_real_name=Insurgo Shipped Integrity Attestation Librem Key #GPG SmartCard desired E-mail address to provision GPG factory reset. # This will be used to construct the ID of the public key: "Real Name (Comment) email@address.org" # Note that some services requires that e-mail address to be real and will send an e-mail to validate it. @@ -130,15 +153,16 @@ oem_gpg_comment=FACTORY RESET ME # LUKS # ########## # LUKS containers are used in Linux to encrypt whole filesystems. -# The whole idea behind OEM reownership depends on the LUKS reencryption of the container from the user when hardware +# The whole idea behind OEM ReOwnership depends on the LUKS reencryption of the container from the user when hardware # is received. Otherwise, the OEM would know the cloned image LUKS Disk Recovery Key and could hand it to authorities. # This provisioning wizard starts by asking you to enter the actual LUKS Disk Recovery Key passphrase to reencrypt the -# container completely, before changing it's passphrase with user selected one. +# containers completely, BOTH sdcard and SSD driver, before changing it's passphrase with user selected one: +# then "new Disk Recovery Passphrase" below. # -# This LUKS Disk Recovery Key, if provided by the OEM **** SHOULD NOT BE MODIFIED ***** +# This LUKS Disk Recovery Key, if provided by the OEM **** SHOULD BE ENTERED AS IS ***** oem_luks_actual_Disk_Recovery_Key=InsurgoTech # This is where you want to define your new Disk Recovery Key passphrase, which will be associated to the reencrypted LUKS -# container after the OEM wizard is over and become the Disk Recovery Key passphrase. +# containers (both sdcard and internal SSD drive) after the OEM wizard is over and become the Disk Recovery Key passphrase. # # This provisioning wizard continues by asking you to enter the desired LUKS Disk Recovery Key passphrase and changes # it. @@ -147,11 +171,14 @@ oem_luks_actual_Disk_Recovery_Key=InsurgoTech # 1-Every boot if no Disk Unlock Key was added to the TPM (NOT RECOMMENDED! could be captured and used on cloned disk) # 2-If the TPM fails (Hardware failure) # 3-If the firmware has been tampered with/upgraded/modified by the user +# 4-When OS upgrades affected the default boot option, to set a new Disk Unlock Key, +# bound to measurements and released by the TPM # -# NOTES: If the Disk Recovery Key Passphrase is lost, the user won't be able to set a new Disk Unlock Key. +# NOTES: If the Disk Recovery Key Passphrase is forgotten, the user won't be able to set a new Disk Unlock Key. # More importantly, in the case of a Operating System core update (Xen, Kernel, initrd (drivers) or grub config, # the Default Boot option will be invalidated, and the only way to boot the system will be by typing this -# Disk Recovery Key Passphrase. ********** CHOOSE IT CAREFULLY SO YOU CAN EASILY REMEMBER IT *********** +# Disk Recovery Key Passphrase, to boot or set a new Disk Unlock Key passphrase. +# ********** CHOOSE IT CAREFULLY SO YOU CAN EASILY REMEMBER IT. FOREVER *********** # # Size constaints: select a Diceware passphrase of at least 3 words. 6 is better. # No need to go crazy here. It's better to have a shorter but strong passphrase you remember and not type often @@ -162,12 +189,15 @@ oem_luks_new_Disk_Recovery_Key=InsurgoTech # # The Disk Unlock Key is another security feature enforced by Heads that makes your computer more trustworthy. # The Disk Unlock Key is released by the Trusted Platform Module (TPM), a cryptographic component on which -# depends Heads to measure and attest firmware integrity, and released only if the measurements of the firmware -# are intact (sealed). In the case the firmware has been modified, that the user lost/forgot his GPG card, -# the Disk Unlock key passphrase will refuse to release the actual Disk Unlock Key and will not boot, unless -# you to type the Disk Recovery Key passphrase. -# -# Heads would not be able to unseal neither TOTP/HOTP in case measurements mismatche and will warn the user. +# depends Heads to measure and attest firmware integrity. The key being released only if the measurements of +# the firmware are intact (sealed). In the case the firmware is modified, the Disk Unlock would not unlock +# the disk, and consequently, will be asked from you to be changed, requiring you to confirm you are +# responsible for those firmware changes. Since its passphrase is useless without TPM released key, the +# TOTP/HOTP would also be invalidated. In corner cases, eg. the TPM fails (hardware), TOTP/HOTP challenges +# would be invalid and your Disk Unlock Key passphrase would not boot the system, unless you to type the +# Disk Recovery Key passphrase. +# +# Heads would not be able to unseal neither TOTP/HOTP in case of measurements mismatch and will warn the user. # # The Disk Unlock Key passphrase will also not be able to unlock the disk if the LUKS header is not # consistent with what was sealed into the TPM when selecting a default boot option. diff --git a/oem-reownership/oem.example b/oem-reownership/oem.example index ff1ef7b88..c4f4b75e1 100755 --- a/oem-reownership/oem.example +++ b/oem-reownership/oem.example @@ -4,13 +4,21 @@ oem_name=Insurgo Open Technologies #The following are states being checked against prior to entering that specific stage. # Once a stage is done, it is appended under /boot/oem # +#If not found in file, shows user mmc partitions (sdcard found in memory expension slot) by mount-sdcard script. +# /boot/oem presence forces the selection of a LUKS encrypted partition to fetch/store secrets from. +# memory card expension slot is enforced through the x230-libremkey board config: "export CONFIG_LINUX_SDHCI=y" +oem_provisioning_partition=/dev/mmcblk0p1 +#In the case such LUKS prepared partition is not found on sdcard inserted in memory expension slot, the following is injected, +# telling the OEM wizard to prompt the user manually for each information it requires +no_automatic_provisioning #If not found in file, shows Onboarding first message containing oem_name above if defined, else "your OEM" is shown onboarding #When not present in this file, reencrypts LUKS container with oem_luks_actual_Disk_Recovery_Key defined under /media/oem-provisioning luks_reencrypted #When not present in this file, changes oem_luks_actual_Disk_Recovery_Key with oem_luks_new_Disk_Recovery_Key defined under /media/oem-provisioning luks_passwd_changed -#When not present in this file, factory resets Librem Key/NitroKey with: oem_gpg_Admin_PIN, oem_gpg_User_PIN, oem_gpg_real_name, oem_gpg_email, oem_gpg_comment, defined under /media/oem-provisioning. +#When not present in this file, factory resets Librem Key/NitroKey with: +# oem_gpg_Admin_PIN, oem_gpg_User_PIN, oem_gpg_real_name, oem_gpg_email, oem_gpg_comment, defined under /media/oem-provisioning. #The wizard generates new keypairs, injects the public key and trust database into the ROM and reboots. #Upon reboot, the oem_gpg_Admin_PIN is used to automatically seal HOTP secret into the Librem Key/NitroKey gpg_factory_resetted @@ -18,4 +26,7 @@ gpg_factory_resetted tpm_reowned #Once all stages are done, the Wizard removes /boot/oem, and ensures that /boot file checksum file is generated and signed with oem_gpg_User_PIN. # -#Then the wizard finally launches the selection of a new boot default, and asks the user if he wants to modify the disk and if he wants to define a Disk Unlock Key. In such case, oem_TPM_Owner_Password is used to seal a new TOTP secret, oem_gpg_Admin_PIN is used to seal a new HOTP secret, and oem_gpg_User_PIN is used to sign configuration files checksums that changed under /boot. +#Then the wizard finally launches the selection of a new boot default, and asks the user if he wants to modify the disk by defining a Disk Unlock Key +# (depends on the following x230-libremkey board config: "CONFIG_OFFER_TPM_LUKS_DISK_UNLOCK_KEY=y"). +# In such case, oem_TPM_Owner_Password is used to seal a new TOTP secret, oem_gpg_Admin_PIN is used to seal a new HOTP secret, +# and oem_gpg_User_PIN is used to sign configuration files checksums digest (kexec_hashes.txt) for which signature is found under /boot/kexec.sig. From 6be2fb84c986f242bde48616785e8ac193b8777d Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Thu, 13 Jun 2019 15:13:08 -0400 Subject: [PATCH 74/91] Clariy and add OEM specific notes --- oem-reownership/oem-provisioning.example | 47 +++++++++++++++--------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/oem-reownership/oem-provisioning.example b/oem-reownership/oem-provisioning.example index 53141a414..1f9c20606 100644 --- a/oem-reownership/oem-provisioning.example +++ b/oem-reownership/oem-provisioning.example @@ -2,24 +2,26 @@ # OEM # ########### # Requirements -# - Stable, OEM ReOwnership branch of Heads (should be streamlines soon) is flashed. -# - (Recommended) Intel ME is neutered per Heads wiki instructions (TODO: PUT HERE) +# - Stable, OEM ReOwnership branch of Heads (should be upstreamed soon) is flashed. +# - (Recommended) Intel ME is neutered per Heads wiki instructions: +# https://github.com/osresearch/heads-wiki/blob/master/Clean-the-ME-firmware.md # -# - OS is preinstalled under LUKS container. (QubesOS recommended) +# - OS is preinstalled under SSD LUKS container. (QubesOS recommended) # - Heads /boot files checksum digest file (/boot/kexec_hashes.txt) is signed (/boot/kexec.sig) # and boot integrity is validated by OEM's public key already present in rom. -# The OEM is encouraged to use the OEM wizard himself to randomly generate strong passphrases. +# The OEM is encouraged to use the OEM wizard himself to randomly generate strong passphrases. # - TPMTOTP/HOTP is already sealed -# - (Recommended) A Disk Unlock Key is set, which partition is defined under /boot/kexec_key_devices.txt) -# - Otherwise, the OEM wizard will prompt the user at Disk Unlock Key to choose between /dev/sda2 and /dev/mmcblk0p2 -# - A prepared sdcard with a LUKS container containing an ext4 partition of ~32Mb is required +# - (Recommended) A Disk Unlock Key is set, for which partition is defined under /boot/kexec_key_devices.txt by Heads +# - Otherwise, the OEM wizard will prompt the user at Disk Unlock Key to choose between /dev/sda2 and /dev/mmcblk0p2 which might +# confuse user +# - A prepared sdcard with a LUKS container containing an ext4 partition is required (32Mb suggested.) # The encryption passphrase is REQUIRED TO BE THE SAME OF THE OS DISK INSTALLATION (Named: actual Recovery Key passphrase) # A 16Gb sdcard, with a second partition containing QubesOS latest iso and signature file is recommended. # # The OEM is advised to use the OEM Wizard himself after having cloned its OEM OS installation onto internal SSD drive. # The OEM having completed OEM reownership should be able to boot OS with Disk Unlock Key, -# for which Heads validates all prior steps automatically, including the sdcard reencryption, which could fail on cheap -# flash memory. +# for which Heads validates integrity automatically. Doing so, he also tests sdcard reencryption, which could fail +# on cheap flash memory. # Having done so, from Heads recovery: # The OEM inserts preformated sdcard in ssdcard memory expension slot then: # "mount-sdcard rw" and then "touch /media/oem-provisioning" and "umount /media" @@ -32,15 +34,26 @@ # reboot # # To activate OEM automatic provisioning, the content of this file needs to be found by Heads under: -# /media/oem-provisioning by calling "mount-sdcard" -# -# Replace variables content with your own manually, or provide a blank or partial file, the OEM Reownership Wizard will take care of the rest! -# BE CONSCIOUS THAT MANUALLY ENTERED VALUES HERE WON'T BE VALIDATED BUT LATER IN THE OEM PROCESS (mainly GPG related ones wich could cause problem). -#The following needs to be put in /boot/oem for OEM name to be shown at OEM Reownership wizard first screen. Else it is going to be "your OEM". -#oem_name=Insurgo Open Technologies +# /media/oem-provisioning after having called "mount-sdcard rw" and selecting "/dev/mmcblk0p1", "touch /media/oem-provisioning" and "umount /media" +# +# The first shell history command (using up arrow in Recovery Shell) contains all the required commands to initiate OEM ReOwnership on next boot: +# mount-sdcard && mount -o remount,rw /media && touch /media/oem-provisioning && mount -o remount,ro /media && mount /boot||true && mount -o remount,rw /boot && echo "oem_name=COMPANY NAME" > /boot/oem && echo "oem_provisioning_partition=/dev/mmcblk0p1" >> /boot/oem && mount -o remount,ro /boot && reboot +# Just replace COMPANY NAME with your own OEM name and you are ready to go, +# keeping a postit on hardware of new Disk Recovery Key passphrase, to be sent with QR Code to customer. # -#On a recovery shell, type the UP arrow key until you reach top of the history buffer. A command is proposed for you to change "YOUR COMPANY" -# to your own. The hardware is then ready to ship and the wizard will accompany the user in reowning the hardware and OEM secrets on next reboot. +# As an OEM, it is suggested that you keep an oem-provisioning file containing +# - actual Disk Recovery Key passphrase (cloned disk OS installation LUKS passphrase) +# - GPG name, e-mail and comment +# +# After having done the Reownership (mostly to reencrypt devices), go on recovery console: +# - mount-sdcard rw +# - vi /media/oem-provisioning +# - Remove everything but "oem_luks_new_Disk_Recovery_Key=InsurgoTech" line and rename it to "oem_luks_actual_Disk_Recovery_Key=InsurgoTech" +# else the user will have to enter it himself in the Wizard, after having already entered it once. +# - umount /media +# +# Replace variables content with your own manually, or provide a blank or partial file. The OEM Reownership Wizard will take care of the rest! +# BE CONSCIOUS THAT MANUALLY ENTERED VALUES HERE WON'T BE VALIDATED BUT LATER IN THE OEM PROCESS (mainly GPG related ones wich could cause problem). # # A manual script "generate_diceware-eom-provisioning.sh" is provided in the current directory, but OEM ReOwnership itself is recommended. # It uses install diceware (in your disto repositories) to prefeed "oem-provisioning.generated" with proper secrets. From e897cd94e0c4180233cb9b6e3187713334dd160b Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Thu, 13 Jun 2019 15:48:53 -0400 Subject: [PATCH 75/91] Gitlab CI cache plays. Doing a complete ./ cache and forcing gitlab to checkout instead of pulling --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7274d629e..b789d5a70 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,7 +7,7 @@ build: stage: build cache: paths: - - ./build + - ./ key: "$CI_COMMIT_REF_SLUG" script: - make BOARD=x230-flash From cc56d6309324eb7092041b4ff11ad5c2d7631772 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Thu, 13 Jun 2019 19:04:50 -0400 Subject: [PATCH 76/91] Forcing reset of git in gitlab config --- .gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b789d5a70..3ff2a8e4c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,6 +10,8 @@ build: - ./ key: "$CI_COMMIT_REF_SLUG" script: + - git fetch origin + - git reset --hard origin/$CI_COMMIT_REF_NAME - make BOARD=x230-flash - make BOARD=x230-libremkey - echo "x230-flash hashes:" From 0b7cf060cff3e81ee13a81cbf7c58c577f64307b Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sun, 16 Jun 2019 21:04:26 -0400 Subject: [PATCH 77/91] Fix bug of OEM asking to validate manually disk unlock key while diceware generated and supposed to be kept. --- initrd/etc/functions | 1 - 1 file changed, 1 deletion(-) diff --git a/initrd/etc/functions b/initrd/etc/functions index 2f3846179..79800860c 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -616,7 +616,6 @@ read_oem_files() echo "Heads will force the user to boot with the Disk Recovery passphrase after 3 failed attempts on each reboot, making this password practically difficult to bruteforce." echo randomize_diceware_passphrases_until_chosen_or_manual 3 UpperFirstLetter Nospace - validate_input_passphrases_are_equal export oem_luks_Disk_Unlock_Key="$passphrase" fi if [ "$to_provision" == "oem_TPM_Owner_Password" ] && [ "$CONFIG_TPM" == "y" ]; then From 42418ad74a41387031fb3c968fd586bec8b18814 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Mon, 17 Jun 2019 12:09:54 -0400 Subject: [PATCH 78/91] OEM: sort provisioned information prior to store them into /media/oem-provisioning --- initrd/etc/functions | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/initrd/etc/functions b/initrd/etc/functions index 79800860c..0414dad82 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -636,7 +636,7 @@ read_oem_files() done mount -o remount,rw /media - env|grep "oem_" > /media/oem-provisioning + env|grep "oem_" | sort > /media/oem-provisioning mount -o remount,ro /media else From 29058dfcd5bce600d943f75fd09556c672aea56b Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Mon, 17 Jun 2019 17:26:15 -0400 Subject: [PATCH 79/91] EOM: add back manual input validation of oem_luks_Disk_Unlock_Key --- initrd/etc/functions | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/initrd/etc/functions b/initrd/etc/functions index 0414dad82..976a2118c 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -616,6 +616,10 @@ read_oem_files() echo "Heads will force the user to boot with the Disk Recovery passphrase after 3 failed attempts on each reboot, making this password practically difficult to bruteforce." echo randomize_diceware_passphrases_until_chosen_or_manual 3 UpperFirstLetter Nospace + while [[ ${#passphrase} -lt 6 ]]; do + echo "We impose a minimal passphrase length of 6 characters." + validate_input_passphrases_are_equal + done export oem_luks_Disk_Unlock_Key="$passphrase" fi if [ "$to_provision" == "oem_TPM_Owner_Password" ] && [ "$CONFIG_TPM" == "y" ]; then From 4b69f5587040f777bd7e3a7d889536a4afbff9f5 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sat, 22 Jun 2019 17:31:12 -0400 Subject: [PATCH 80/91] OEM : add instruction on GPG public Key Comment: Cannot be empty. --- initrd/etc/functions | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/initrd/etc/functions b/initrd/etc/functions index 976a2118c..d08470411 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -559,7 +559,7 @@ read_oem_files() echo "Differenciates usage of public keys that would be associated with same Real Name and E-Mails addresses if many. (e.g: for E-Mail correspondants)" passphrase="" while [[ ${#passphrase} -gt 60 ]] || [[ -z "$passphrase" ]]; do - echo "We have limitations for GPG public key associated comment: maximal length of 60 characters" + echo "We have limitations for GPG public key associated comment: maximal length of 60 characters. Cannot be empty." validate_input_passphrases_are_equal done export oem_gpg_comment="$passphrase" From 89115ee23d7949fa935f773c2421a0167d9ba6db Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sun, 23 Jun 2019 06:26:22 -0400 Subject: [PATCH 81/91] OEM: Add a last whiptail warning before Reownership ends, just prior enforcing Disk Unlock Key passphrase --- initrd/etc/functions | 3 +++ 1 file changed, 3 insertions(+) diff --git a/initrd/etc/functions b/initrd/etc/functions index d08470411..4813c00d5 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -725,6 +725,9 @@ check_onboarding_progress() fi fi else + #We just deleted the /boot/oem file and are at the last possible iteration of this function. + whiptail --title 'OEM ReOwnership Wizard last step!' --msgbox \ + "Time to set a new boot default and set a Disk Unlock Key passphrase\n\nPlease hit Enter to continue" 30 60 reset_disk_unlock_key return fi From 0f3fd5d95ef070431f58c93e262a0ca033c0c1fd Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sun, 23 Jun 2019 07:35:10 -0400 Subject: [PATCH 82/91] OEM: Last message adjustments before ending OEM reownership --- initrd/etc/functions | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/initrd/etc/functions b/initrd/etc/functions index 4813c00d5..cd9fff459 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -727,7 +727,7 @@ check_onboarding_progress() else #We just deleted the /boot/oem file and are at the last possible iteration of this function. whiptail --title 'OEM ReOwnership Wizard last step!' --msgbox \ - "Time to set a new boot default and set a Disk Unlock Key passphrase\n\nPlease hit Enter to continue" 30 60 + "Time to set a new boot default and set a Disk Unlock Key passphrase\nAfter this step, you will get to default boot menu.\nOEM reownership will then be completed.\n\nPlease hit Enter to continue" 30 60 reset_disk_unlock_key return fi From 01baf58b90d06ca4875c28e9da8a49b63479fbcb Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Tue, 25 Jun 2019 13:43:18 -0400 Subject: [PATCH 83/91] OEM: Remove requirement of GPG Admin PIN to not contain space, the bug having been corrected and upstreamed. --- initrd/etc/functions | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/initrd/etc/functions b/initrd/etc/functions index cd9fff459..8e6778fd5 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -506,8 +506,8 @@ read_oem_files() echo "Better choose a simple, short passphrase that you'll remember forever then one long that would lock yourself off because forgotten." echo "Suggested passphrase length: 2 words diceware passphrase." randomize_diceware_passphrases_until_chosen_or_manual 2 UpperFirstLetter Nospace - while [[ ${#passphrase} -lt 8 || ${#passphrase} -gt 20 ]] || [ "$passphrase" != "${passphrase% *}" ]; do - echo "We have limitations on Admin PIN: minimal 8 and maximal length of 20 characters, NO SPACE!" + while [[ ${#passphrase} -lt 8 || ${#passphrase} -gt 20 ]]; do + echo "We have limitations on Admin PIN: minimal 8 and maximal length of 20 characters" validate_input_passphrases_are_equal done notify "oem_gpg_Admin_PIN=$passphrase" From 879aada8619a0f6e2b5fd6f30f63e68018e55969 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Tue, 25 Jun 2019 17:06:05 -0400 Subject: [PATCH 84/91] cryptsetup: add LUKS nuke patchset from https://gitlab.com/kalilinux/packages/cryptsetup/blob/3ddbbb67ade4e60f4bcacd26d8647ae04c8fabb5/debian/patches/cryptsetup_nuke_keys.patch --- patches/cryptsetup-1.7.5.patch | 125 +++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/patches/cryptsetup-1.7.5.patch b/patches/cryptsetup-1.7.5.patch index c36d36fd8..4364769e5 100644 --- a/patches/cryptsetup-1.7.5.patch +++ b/patches/cryptsetup-1.7.5.patch @@ -19,3 +19,128 @@ diff -u --recursive ../../clean/cryptsetup-1.7.3/src/Makefile.in ./cryptsetup-1. @VERITYSETUP_TRUE@ @POPT_LIBS@ @VERITYSETUP_TRUE@veritysetup_CFLAGS = $(cryptsetup_CFLAGS) + +diff -ruN cryptsetup-1.7.5/lib/libcryptsetup.h cryptsetup-1.7.5-patched/lib/libcryptsetup.h +--- cryptsetup-1.7.5/lib/libcryptsetup.h 2017-04-27 02:42:53.000000000 -0400 ++++ cryptsetup-1.7.5-patched/lib/libcryptsetup.h 2019-06-25 16:40:29.553000000 -0400 +@@ -758,6 +758,8 @@ + #define CRYPT_ACTIVATE_RESTART_ON_CORRUPTION (1 << 9) + /** dm-verity: ignore_zero_blocks - do not verify zero blocks */ + #define CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS (1 << 10) ++/** key slot is a nuke, will wipe all keyslots */ ++#define CRYPT_ACTIVATE_NUKE (1 << 30) + + + /** +diff -ruN cryptsetup-1.7.5/lib/luks1/keymanage.c cryptsetup-1.7.5-patched/lib/luks1/keymanage.c +--- cryptsetup-1.7.5/lib/luks1/keymanage.c 2017-04-27 02:42:53.000000000 -0400 ++++ cryptsetup-1.7.5-patched/lib/luks1/keymanage.c 2019-06-25 16:40:29.553000000 -0400 +@@ -966,6 +966,24 @@ + + if (!r) + log_verbose(ctx, _("Key slot %d unlocked.\n"), keyIndex); ++ ++ /* check whether key in key slot is a NUKE (then wipe all keyslots) */ ++ if(vk->key[0] == 0) { ++ int i=1; ++ ++ while(ikeylength && vk->key[i]==0) { ++ i++; ++ } ++ if(i == vk->keylength) { ++ /* vk is all 0's: WIPE ALL KEYSLOTS and log a fake error message */ ++ log_err(ctx, _("Failed to read from key storage.\n")); ++ for(i=0; i 0) && ((keyslot & CRYPT_ACTIVATE_NUKE) != 0) ) { ++ nuke = 1; ++ keyslot ^= CRYPT_ACTIVATE_NUKE; ++ } ++ if( (keyslot < 0) && ((keyslot & CRYPT_ACTIVATE_NUKE) == 0) ) { ++ nuke = 1; ++ keyslot ^= CRYPT_ACTIVATE_NUKE; ++ } ++ + r = keyslot_verify_or_find_empty(cd, &keyslot); + if (r) + return r; +@@ -1751,6 +1761,10 @@ + goto out; + } + ++ if(nuke) { ++ memset(vk->key, '\0', vk->keylength); ++ } ++ + r = LUKS_set_key(keyslot, new_password, new_passwordLen, + &cd->u.luks1.hdr, vk, cd->iteration_time, &cd->u.luks1.PBKDF2_per_sec, cd); + if(r < 0) +diff -ruN cryptsetup-1.7.5/src/cryptsetup.c cryptsetup-1.7.5-patched/src/cryptsetup.c +--- cryptsetup-1.7.5/src/cryptsetup.c 2017-04-27 02:42:53.000000000 -0400 ++++ cryptsetup-1.7.5-patched/src/cryptsetup.c 2019-06-25 16:40:29.554000000 -0400 +@@ -37,6 +37,7 @@ + static const char *opt_uuid = NULL; + static const char *opt_header_device = NULL; + static const char *opt_type = "luks"; ++static int currentlyNuking = 0; + static int opt_key_size = 0; + static long opt_keyfile_size = 0; + static long opt_new_keyfile_size = 0; +@@ -1036,6 +1037,9 @@ + if (r < 0) + goto out; + ++ if(currentlyNuking == 1) { ++ opt_key_slot ^= CRYPT_ACTIVATE_NUKE; ++ } + r = crypt_keyslot_add_by_passphrase(cd, opt_key_slot, + password, password_size, + password_new, password_new_size); +@@ -1048,6 +1052,15 @@ + return r; + } + ++static int action_luksAddNuke(void) ++{ ++ int results; ++ currentlyNuking = 1; ++ results = action_luksAddKey(); ++ currentlyNuking = 0; ++ return(results); ++} ++ + static int action_luksChangeKey(void) + { + const char *opt_new_key_file = (action_argc > 1 ? action_argv[1] : NULL); +@@ -1386,6 +1399,7 @@ + { "erase", action_luksErase , 1, 1, N_(""), N_("erase all keyslots (remove encryption key)") }, + { "luksFormat", action_luksFormat, 1, 1, N_(" []"), N_("formats a LUKS device") }, + { "luksAddKey", action_luksAddKey, 1, 1, N_(" []"), N_("add key to LUKS device") }, ++ { "luksAddNuke", action_luksAddNuke, 1, 1, N_(" []"), N_("add NUKE to LUKS device") }, + { "luksRemoveKey",action_luksRemoveKey,1, 1, N_(" []"), N_("removes supplied key or key file from LUKS device") }, + { "luksChangeKey",action_luksChangeKey,1, 1, N_(" []"), N_("changes supplied key or key file of LUKS device") }, + { "luksKillSlot", action_luksKillSlot, 2, 1, N_(" "), N_("wipes key with number from LUKS device") }, + From 3ddaab76169ead57f9cb3acf779817dbbc3494b2 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Thu, 27 Jun 2019 09:53:20 -0400 Subject: [PATCH 85/91] factory-reset-libremkey: Remove no space constraint on GPG Admin PIN --- initrd/bin/factory-reset-libremkey.sh | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/initrd/bin/factory-reset-libremkey.sh b/initrd/bin/factory-reset-libremkey.sh index bf47cdc18..dc14b4149 100755 --- a/initrd/bin/factory-reset-libremkey.sh +++ b/initrd/bin/factory-reset-libremkey.sh @@ -40,14 +40,12 @@ if (whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'Factory Reset and reowner };done gpgcard_user_pass=$gpgcard_user_pass1 - while [[ "$gpgcard_admin_pass1" != "$gpgcard_admin_pass2" ]] || [[ ${#gpgcard_admin_pass1} -lt 8 || ${#gpgcard_admin_pass1} -gt 20 ]] || [ "$gpgcard_admin_pass1" != "${gpgcard_admin_pass1% *}" ]; do + while [[ "$gpgcard_admin_pass1" != "$gpgcard_admin_pass2" ]] || [[ ${#gpgcard_admin_pass1} -lt 8 || ${#gpgcard_admin_pass1} -gt 20 ]]; do { - echo -e "\nChoose your new GPG card admin password that will be typed when managing GPG smartcard (HOTP sealing, managing key, etc).\nIt needs to be a least 8 but not more then 20 characters WHILE NOT CONTAINING SPACES:" + echo -e "\nChoose your new GPG card admin password that will be typed when managing GPG smartcard (HOTP sealing, managing key, etc).\nIt needs to be a least 8 but not more then 20 characters:" read -s gpgcard_admin_pass1 echo -e "\nRetype admin password:" read -s gpgcard_admin_pass2 - - if [[ "$gpgcard_admin_pass1" != "$gpgcard_admin_pass2" ]] || [ "$gpgcard_admin_pass1" != "${gpgcard_admin_pass1% *}" ]; then echo "Passwords typed were different or contained spaces."; fi };done gpgcard_admin_pass=$gpgcard_admin_pass1 From bb7e89e034bdf77b7a93da3345903bfe8182ca22 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Thu, 27 Jun 2019 18:03:13 -0400 Subject: [PATCH 86/91] OEM: make diceware suggested passwords sepearated by spaces (Since GPG Admin PIN/HOTP doesn't require to not have space anymore) --- initrd/etc/functions | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/initrd/etc/functions b/initrd/etc/functions index 8e6778fd5..bdb8c8ad0 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -505,7 +505,7 @@ read_oem_files() echo "There is no need to have a super strong passphrase here, it will be locked after 3 bad attempts in the GPG smartcard itself." echo "Better choose a simple, short passphrase that you'll remember forever then one long that would lock yourself off because forgotten." echo "Suggested passphrase length: 2 words diceware passphrase." - randomize_diceware_passphrases_until_chosen_or_manual 2 UpperFirstLetter Nospace + randomize_diceware_passphrases_until_chosen_or_manual 2 UpperFirstLetter while [[ ${#passphrase} -lt 8 || ${#passphrase} -gt 20 ]]; do echo "We have limitations on Admin PIN: minimal 8 and maximal length of 20 characters" validate_input_passphrases_are_equal @@ -522,7 +522,7 @@ read_oem_files() echo echo "There is no need to have a super strong passphrase here, it will be locked after 3 bad attempts in the GPG smartcard." echo "Suggested length: 2 random words diceware passphrase." - randomize_diceware_passphrases_until_chosen_or_manual 2 UpperFirstLetter Nospace + randomize_diceware_passphrases_until_chosen_or_manual 2 UpperFirstLetter while [[ ${#passphrase} -lt 6 || ${#passphrase} -gt 20 ]]; do echo "We have limitations for GPG User PIN: minimal 6 and maximal length of 20 characters" validate_input_passphrases_are_equal @@ -589,7 +589,7 @@ read_oem_files() echo echo "If forgotten, the content of both $oem_name shipped microsd disk and computer internal disk will be lost forever." echo "It is suggested that you pick a diceware passphrase of 6+ words. Make something emotionnaly involving from those words." - randomize_diceware_passphrases_until_chosen_or_manual 6 UpperFirstLetter Nospace + randomize_diceware_passphrases_until_chosen_or_manual 6 UpperFirstLetter while [[ ${#passphrase} -lt 25 ]]; do echo "We impose a minimal requirement of 25 characters for LUKS Disk Recovery Passphrase." echo "Remember that a 5 words diceware passphrase would have took 165 days to break in 2013 for the NSA." @@ -615,7 +615,7 @@ read_oem_files() echo "A diceware randomly selected passphrase of 3 words is more then enough, considering that the TPM is rate limiting the attempts." echo "Heads will force the user to boot with the Disk Recovery passphrase after 3 failed attempts on each reboot, making this password practically difficult to bruteforce." echo - randomize_diceware_passphrases_until_chosen_or_manual 3 UpperFirstLetter Nospace + randomize_diceware_passphrases_until_chosen_or_manual 3 UpperFirstLetter while [[ ${#passphrase} -lt 6 ]]; do echo "We impose a minimal passphrase length of 6 characters." validate_input_passphrases_are_equal From 53e863d32c77459a06f1cebcb1f08a6954569df1 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Thu, 27 Jun 2019 18:16:14 -0400 Subject: [PATCH 87/91] OEM: readd automatic provisioning of GPG Admin PIN in seal-libremkey --- initrd/bin/seal-libremkey | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/initrd/bin/seal-libremkey b/initrd/bin/seal-libremkey index 2e428d83d..587ba555a 100755 --- a/initrd/bin/seal-libremkey +++ b/initrd/bin/seal-libremkey @@ -59,8 +59,12 @@ if ! libremkey_hotp_verification info ; then fi fi -read -s -p "Enter your Librem Key Admin PIN" admin_pin -echo +if [ -z "$oem_gpg_Admin_PIN" ]; then + read -s -p "Enter your Librem Key Admin PIN" admin_pin + echo +else + admin_pin=$(echo -n "$oem_gpg_Admin_PIN") +fi libremkey_hotp_initialize "$admin_pin" $HOTP_SECRET $counter_value if [ $? -ne 0 ]; then From 96c710e882a9f86e9900065efaa5b84055a68f36 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sat, 29 Jun 2019 21:14:57 -0400 Subject: [PATCH 88/91] OEM: Disk Unlock Key Passphrase was missing a notify to confirm exported secret value --- initrd/etc/functions | 1 + 1 file changed, 1 insertion(+) diff --git a/initrd/etc/functions b/initrd/etc/functions index bdb8c8ad0..0436239b6 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -620,6 +620,7 @@ read_oem_files() echo "We impose a minimal passphrase length of 6 characters." validate_input_passphrases_are_equal done + notify "oem_luks_Disk_Unlock_Key=$passphrase" export oem_luks_Disk_Unlock_Key="$passphrase" fi if [ "$to_provision" == "oem_TPM_Owner_Password" ] && [ "$CONFIG_TPM" == "y" ]; then From 47d024e9f493491e1a2b11c8abace1e97d092139 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sun, 30 Jun 2019 17:48:09 -0400 Subject: [PATCH 89/91] OEM: small typos correction --- initrd/etc/functions | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/initrd/etc/functions b/initrd/etc/functions index 0436239b6..e65e397e9 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -568,7 +568,7 @@ read_oem_files() clear echo "$to_provision: actual Disk Recovery Key passphrase" echo - echo "After disks reencryption, you'll have to enter your own, new Disk Recovery Key passphrase to unlock both OEM provided microsd card and insternal disks." + echo "After disks reencryption, you'll have to enter your own, new Disk Recovery Key passphrase to unlock both OEM provided microsd card and internal disks." echo echo "The actual LUKS Disk Recovery Key passphrase was provided to you from $oem_name. Type it here as provided." echo "The actual LUKS Disk Recovery Key passphrase is used to decrypt both microsd and internal disks until reencrypted by this Wizard." @@ -606,7 +606,7 @@ read_oem_files() echo "$to_provision: Disk Unlock Key passphrase" echo echo "Chosen LUKS Disk Unlock Key passphrase will be requested at each boot until the a next OS boot default will be requested from OS upgrade." - echo "The LUKS Disk Unlock Key is an additional security measure of Heads which permits disk decryption only if the firmware measurements valid." + echo "The LUKS Disk Unlock Key is an additional security measure of Heads which permits disk decryption only if the firmware measurements are valid." echo "As a consequence, the Disk Unlock Key passphrase is bound to this computer Trusted Platform Module (TPM) only." echo "As a result, someone cloning your disk and trying to decrypt its content by typing this Disk Unlock Key passphrase will be unsuccessful." echo "If forgotten, no problem. Select a new boot default and you will be prompted to enter chosen Disk Recovery Key Passphrase prior to defining a new Disk Unlock Key passphrase." From 8f5d0b1a665637d1a09227a07e0a111f706d6681 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sun, 30 Jun 2019 19:23:47 -0400 Subject: [PATCH 90/91] gui-init: Fix 'Update checksums and sign all files in /boot' whiptail message over multiple lines --- initrd/bin/gui-init | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/initrd/bin/gui-init b/initrd/bin/gui-init index e225c6af2..8dd4db3c9 100755 --- a/initrd/bin/gui-init +++ b/initrd/bin/gui-init @@ -75,7 +75,7 @@ verify_global_hashes() update_checksums() { if (whiptail --title 'Update Checksums and sign all files in /boot' \ - --yesno "You have chosen to update the checksums and sign all of the files in /boot.\n\nThis means that you trust that the files in /boot have not been tampered with.\n\nYou will need your GPG key to continue and this change will modify your disk.\n\nDo you want to continue?" 16 90) then + --yesno "You have chosen to update the checksums and sign all of the files in /boot.\n\nThis means that you trust that the files in /boot have not been tampered\n with.\n\nYou will need your GPG key to continue and this change will modify your\n disk.\n\nDo you want to continue?" 16 90) then mount_boot mount -o rw,remount /boot From ca021d2858c7c96893b43f6020622a1950e017f8 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Mon, 1 Jul 2019 13:07:55 -0400 Subject: [PATCH 91/91] reencrypt-luks: uniformisation of wording --- initrd/bin/reencrypt-luks | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/initrd/bin/reencrypt-luks b/initrd/bin/reencrypt-luks index f756fad29..006c2b6c9 100755 --- a/initrd/bin/reencrypt-luks +++ b/initrd/bin/reencrypt-luks @@ -125,7 +125,7 @@ if [ -n "$reownership_state" ] && [ "$reownership_state" = "luks_password_change if [ -n "$SDCARD_MOUNT_DEVICE" ]; then umount /media 2> /dev/null cryptsetup luksClose /dev/mapper/sdcarddev 2> /dev/null - warn "Changing $SDCARD_MOUNT_DEVICE LUKS encrypted disk passphrase to new Recovery Disk Key passphrase..." + warn "Changing $SDCARD_MOUNT_DEVICE LUKS encrypted disk passphrase to new Disk Recovery Key passphrase..." cryptsetup luksChangeKey "$SDCARD_MOUNT_DEVICE" --key-slot 0 --key-file=/tmp/oem_luks_actual_Disk_Recovery_Key /tmp/oem_luks_new_Disk_Recovery_Key fi mount -o remount,rw /boot