Changes:
- As per master: when TOTP cannot unseal TOTP, user is prompted to either reset or regenerate TOTP
- Now, when either is done and a previous TPM Disk Unlock Key was setuped, the user is guided into:
- Regenerating checksums and signing them
- Regenerating TPM disk Unlock Key and resealing TPM disk Unlock Key with passphrase into TPM
- LUKS header being modified, user is asked to resign kexec.sig one last time prior of being able to default boot
- When no previous Disk Unlock Key was setuped, the user is guided into:
- The above, plus
- Detection of LUKS containers,suggesting only relevant partitions
- Addition of TRACE and DEBUG statements to troubleshoot actual vs expected behavior while coding
- Were missing under TPM Disk Unlock Key setup codepaths
- Fixes for #645 : We now check if only one slots exists and we do not use it if its slot1.
- Also shows in DEBUG traces now
Unrelated staged changes
- ash_functions: warn and die now contains proper spacing and eye attaction
- all warn and die calls modified if containing warnings and too much punctuation
- unify usage of term TPM Disk Unlock Key and Disk Recovery Key
prepare_thumb_drive: default to creating 10% LUKS container on usb drive, prompts for passphrase is not provided and scan drives if no --device specified
NOTE: qemu usb_thumb drive of 128 mb are not big enough so that 10% of it (12mb) can be used to create thumb drive.
Adds:
- e2fsprogs to support ext4 filesystem creation through mke2fs
- add /etc/mke2fs.conf so that mke2fs knows how to handle ext2/ext3/ext4
- removes mke2fs support from busybox
- bump busybox to latest version which adds cpu accelerated hash functions (not needed per se here)
- Adds exfatprogs to have mkfs.exfat and fsck.exfat
- Adds prepare_thumb_drive /etc/luks-functions to be able to prepare a thumb drive with percentage of drive assigned to LUKS, rest to exfat
- Modify most board configs to test space requirements failing
- Talos2 linux config: add staging Exfat support
- Make e2fsprogs and exfatprogs included by default unless explicitely deactivate in board configs
- Change cryptsetup calls : luksOpen to open and luksClose to close to addresss review
- etc/luks_functions: cleanup
GOAL here is to have secure thumb drive creation which Heads will be able to use to backup/restore/use generated GPG key material in the future (next PR)
HOTP/TOTP secrets don't have to be printable. Use binary data to
include 160 bits of entropy instead of just 80.
The secret is still limited to 20 bytes. Most keys now support up to
40 bytes, but tpmtotp is still limited to 20 bytes.
Move the truncation to 20 bytes a bit later, for future improvements to
detect the key's actual limit.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
flash.sh had a special mode to read (like -r) and then sha256sum the
resulting file. This is no different from just a read followed by a
sha256sum, and the only caller also had logic to sha256sum a cached
file anyway.
Just use flash.sh -r and sha256sum the result.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
Some prompts were missed when changing to 0 80 the first time around,
and some new ones were added thinking that size was intentional.
Replace '16 60' with '0 80' globally.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
Allow configuring the root hash feature when the variables are not set
initially. This worked on Librem boards because the boards all have
defaults for these variables, but didn't work when those defaults were
not present.
Fix set_config function to put quotes around an added variable's value.
Change load_config_value function to default to empty, so it can be
used with non-boolean variables. None of the existing callers cared
about the 'n' default (boolean variables should always be tested ="y"
or !="y" anyway).
Use load_config_value in config-gui.sh for boot device and the root
hash parameters, so unset defaults do not cause a failure. Improve the
prompts so the "current value" text only appears if there is a current
value. Use set_config instead of replace_config so the variables will
be added if needed.
Prevent enabling the root hash feature if it hasn't been configured
yet.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
Remove brand name from this configuration variable. For backward
compatibility, update config.user in init if the branded variable is
present.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
Stop manually loading config values, just update config in environment.
Never test values against "n", since many default to empty. Always
test ="y" or !="y", any other value is off.
Add set_user_config() function to set a value in config.user,
combine configs, and update config in environment. Use it in setting
implementations.
Remove toggle_config, it wasn't very useful because the settings still
test y/n in order to show specific confirmation and success messages.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
Blob jail provides device firmware blobs to the OS, so the OS does not
have to ship them. The firmware is passed through the initrd to
/run/firmware, so it works with both installed and live OSes, and there
are no race conditions between firmware load and firmware availability.
The injection method in the initrd is specific to the style of init
script used by PureOS, since it must add a copy command to copy the
firmware from the initrd to /run. If the init script is not of this
type, boot proceeds without device firmware.
This feature can be enabled or disabled from the config GUI.
Blob jail is enabled automatically if the Intel AX200 Wi-Fi module is
installed and the feature hasn't been explicitly configured.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Restricted Boot mode only allows booting from signed files, whether that
is signed kernels in /boot or signed ISOs on mounted USB disks. This
disables booting from abitrary USB disks as well as the forced "unsafe"
boot mode. This also disables the recovery console so you can't bypass
this mode simply by running kexec manually.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
PureBoot Basic mode provides the full Linux userspace in firmware from
Heads without requiring verified boot or a Librem Key. Basic and
verified boot can be switched freely without changing firmware, such as
if a Librem Key is lost.
PureBoot Basic can apply firmware updates from a USB flash drive, and
having a complete Linux userspace enables more sophisticated recovery
options.
Basic mode boots to the first boot option by default, setting a default
is not required. This can be configured in the config GUI.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
Add these two functions for use in config-gui.sh for future toggles.
load_config_value() obtains the value of a config setting, defaulting
to 'n'. get_config_display_action() displays 'Enable' or 'Disable'
depending on the current value.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
enable_usb_storage() inserts usb-storage.ko if not already loaded, then
waits for USB storage devices to appear.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
pause_automatic_boot() prompts that an automatic boot is about to occur
and allows the user to interrupt it.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
Extract utilities from config-gui.sh for use in additional config
settings. read_rom() reads the current ROM with a message for failure.
replace_rom_file() replaces a CBFS file in a ROM. set_config() sets a
configuration variable in a file.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
On machines without a TPM, we'd still like some way for the BIOS to
attest that it has not been modified. With a Librem Key, we can have the
BIOS use its own ROM measurement converted to a SHA256sum and truncated
so it fits within an HOTP secret. Like with a TPM, a malicious BIOS with
access to the correct measurements can send pre-known good measurements
to the Librem Key.
This approach provides one big drawback in that we have to truncate the
SHA256sum to 20 characters so that it fits within the limitations of
HOTP secrets. This means the possibility of collisions is much higher
but again, an attacker could also capture and spoof an existing ROM's
measurements if they have prior access to it, either with this approach
or with a TPM.
Signed-off-by: Kyle Rankin <kyle.rankin@puri.sm>
TPM password must be 1-32 characters. Loop if the password is not
valid or the repeated password doesn't match, so the user can try
again.
Move prompt_new_owner_password to functions and use in both gui-init
and tpm-reset.
Fixes#1336
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
init must use busybox ash because it is used on legacy-flash boards.
Change shebang, move needed functions to ash_functions.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
Multiple traps overwrite each other. While no tpmr functions have more
than one trap right now, it is fragile, and the quoting is complex due
to double expansion. Use at_exit to add exit handlers that accumulate
and do not require special quoting.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
We just set the TPM owner password, so there's no need to make the user
enter it again. Eliminates some failure modes if the user mistypes it
or enters the wrong password.
Allow optionally passing in the TPM owner password in tpmr seal,
check_tpm_counter(), seal-totp, and generate_totp_htop(). The user is
still prompted if the password is needed but was not provided, so
existing uses in other contexts continue to work unchanged.
Prompt for the password in reset_tpm() and pass it down to each of the
above.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
gui-init: do not consume two unseal attempt to unseal both totp and hotp + cosmetic changes (slow down TPM DA lockout)
kexec-seal-key: Add DEBUG statement for PCR precalc
seal-totp: add DEBUG statements regarding skipping of PCR5 and PCR6 involvement into TOTP/HOTP sealing ops
seal-hotpkey: Add DEBUG statements related to reuse of TOTP sealed secret
tpmr: add DO_WITH_DEBUG calls to output pcrread and extend calls
tpmr: typo correction stating TRACE calls for tpm2 where it was for tpm1
tpmr: add DO_WITH_DEBUG calls for calcfuturepcr
functions: Cosmetic fix on pause_recovery asking user to press Enter to go to recovery shell on host console when board defines CONFIG_BOOT_RECOVERY_SERIAL
Not so related but part of output review and corrections:
kexec-insert-key: cosmetic changes prepending "+++" to disk related changes
kexec-save-default: cosmetic changes prepending "+++" to disk related changes
config/coreboot-qemu-tpm*.config: add ccache support for faster coreboot rebuild times
Provide mask_param() function to uniformly mask secret parameters,
while still indicating whether they are empty.
Extend DO_WITH_DEBUG to allow masking a password parameter by position,
using mask_param(). Move from ash_functions to functions (isn't used
by ash scripts).
Mask password parameters in kexec-unseal-key and tpmr seal. Use
mask_param() on existing masked params in tpmr.
Trim more troubleshooting output from tpm2_extend() in tpmr.
Clarify tpmr kexec_finalize echo; it's the TPM's platform heirarchy,
users might not know what this was referring to.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
Busybox no longer has CONFIG_BASH since we are deploying bash on most
boards. We also should clearly indicate which scripts cannot use
bashisms.
Change shebang in x230-flash.init, t430-flash.init, flash.sh to
/bin/ash. Execute /bin/sh for interactive shells.
Move key functions needed by those scripts to initrd/etc/ash_functions.
Source ash_functions instead of functions in those scripts, so any
bashisms in other functions won't break parsing of the script in ash.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
Use /bin/sh (ash in busybox builds) for interactive shells, not bash.
Preparation for trimming interactive features from bash to reduce size.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
Trace parameters to seal/unseal and some key tpm2 invocations. Trace
invocation of tpmr seal/unseal for disk unlock key.
Add DO_WITH_DEBUG() to trace a command and parameters, then execute it.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
- /tmp/debug.log is created and appended by all TRACE and DEBUG calls in code
- fix some logic errors seen when no DEBUG entry were outputted in /tmp/debug.log
Most logic throughout Heads doesn't need to know TPM1 versus TPM2 (and
shouldn't, the differences should be localized). Some checks were
incorrect and are fixed by this change. Most checks are now unchanged
relative to master.
There are not that many places outside of tpmr that need to
differentiate TPM1 and TPM2. Some of those are duplicate code that
should be consolidated (seal-hotpkey, unseal-totp, unseal-hotp), and
some more are probably good candidates for abstracting in tpmr so the
business logic doesn't have to know TPM1 vs. TPM2.
Previously, CONFIG_TPM could be variously 'y', 'n', or empty. Now it
is always 'y' or 'n', and 'y' means "any TPM". Board configs are
unchanged, setting CONFIG_TPM2_TOOLS=y implies CONFIG_TPM=y so this
doesn't have to be duplicated and can't be mistakenly mismatched.
There were a few checks for CONFIG_TPM = n that only coincidentally
worked for TPM2 because CONFIG_TPM was empty (not 'n'). This test is
now OK, but the checks were also cleaned up to '!= "y"' for robustness.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
-coreboot support of TPM v2.0 (shared config for TPM2 support across all 4 previous variations)
-swtpm set to be launched under TPM v2.0 mode under board config
-Documentation file under each board.md softlinks to qemu-coreboot-fbwhiptail-tpm1.md (which has been generalized)
This is skeleton for TPM v2 integration under Heads
-------------
WiP
TODO:
- libcurl cannot be built as a tpm2-tools dependency as of now not sure why. curl currently needs to be added in board config to be built
- Note: tpm-reset (master and here) needs some review, no handle of no tpm use case. Caller is responsible to not call it otherwise does nothing
- init tries to bind fd and fails currently
- Note: Check if whiptail is different of fbwhiptail in clearing screen. As of now every clear seems to be removed, still whiptail clears previous console output
- When no OS' /boot can be mounted, do not try to TPM reset (will fail)
- seal-hotpkey is not working properly
- setting disk unlock key asks for TPM ownership passphrase (sealing in NV requires ownership, but text is misleading user as if reowning TPM)
- We should cache input, feed tpm behind the scene and wipe passphrase and state clearly that this is TPM disk unlock kye passphrase.
- primary key from TPM2 is invalid most of the time from kexec-select-boot and verifying global hashes but is setuped correctly at disk unlock key setup
- would be nice to take advantage of bash function tracing to understand where we are for debugging purposes, code takes ash in consideration only
- tpmr says it implements nv calls but actually doesn't. Removing those falsely wrapped functions would help.
- Implementing them would be better
- REVIEW TODOS IN CODE
- READD CIRCLECI CONFIG
Current state:
- TPM unseal works without disk unlock key and generates TOTP properly (was missing die condition at unseal to not produce always good TOTP even if invalid)
- TPM disk encryption key fails. Hypothesis is that sealing with USB drivers loaded and measures in inconsistent with sealed with/without.
- TPM disk unsealing happens without USB modules being loaded in non-HOTP setup. This fails.
- Current tests are with fbwhiptail (no clear called so having traces on command line of what happens)
- Testing with HOTP implementation for sealing/unsealing since that forces USB module loads on each boot to remove this from failing possibilities
- Add TRACE function tracing output under etc/functions, depending on CONFIG_ENABLE_FUNCTION_TRACING_OUTPUT enabled in board configs
- Replace current DEBUG to TRACE calls in code, reserving DEBUG calls for more verbose debugging later on (output of variables etc)
- add 'export CONFIG_ENABLE_FUNCTION_TRACING_OUTPUT=y' in qemu-coreboot(fb)whiptail-tpm1(-hotp) boards to see it in action
Adds check to detect device formatted as fat32 without partition table.
With fat32 fdisk does not print message about invalid partition table
and instead it'll print an empty table with header.
In both cases total output has the same length of 5 lines: 3 about
device info, 1 empty line and the 5th will be the table header or
invalid partition message.
Signed-off-by: Daniel Pineda <daniel.pineda@puri.sm>
Since it's not supposed to be shell safe, just display safe
inside double quotes, we can allow some more characters.
Also fix the escape character not being escaped.
busybox sha256sum will create a checksum file for uncommon file names
(e.g. /boot/foo"$\n"bar), but fail to verify that exact file.
https://bugs.busybox.net/show_bug.cgi?id=14226
Thus disallow all files in /boot/ with strange file names at the time of
signing for now. Verifying in the presence of new files with such file
names in /boot/ is no issue for the kexec_tree verification due to the
previously implemented escaping mechanism.
Attempt to fix the following issues:
1. unescaped file names may let an attacker display arbitrary
whiptail prompts --> escape, original code by @JonathonHall-Purism
2. whiptail itself allows escape characters such as \n
--> use an escape character not used by whiptail, i.e. #
3. performance issues caused by diff'ing too early -->
only generate a diff to display to the user, if an actual issue is
found
Extract exclusion for unpartitioned block device of partitioned media
to gui_functions, and exclude them even if kernel hasn't listed the
partitions yet. (Fixes flash/USB boot prompts incorrectly trying to
use the whole device for partitioned media the first time.)
Ignore block devices of size 0, like empty USB SD card readers.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
bin/kexec-parse-boot: test 2bb1f52bf5 that fix correctly comma seperated arguments.
Still TODO: when booting, Heads tries to find where the ISO with /dev/disk/by-label/ARCH_202202 wich is never brought up. uuids could, not sure why the label is not brought up correctly. Maybe an issue in the way Arch makes the ISO.
@tslilc : Any idea to continue #584 or modify #762?
Some devices, like older Librem laptops, use BAT vs BAT0 for the
primary battery. Accomodate this by using BAT* instead of BAT0.
Could break on multi-battery devices, but none supported in tree
currently so more of a theoretical problem.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Grepping on just 'Disk' can lead to disk UUID identifier strings
being added to /tmp/disklist, which then fail to parse later on.
Avoid this by grepping on 'Disk /dev' instead.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Modify update_checksums() to return 0/1 on success/failure, and modify
callers to notify the user on error with a GUI msg.
Set background color as appropriate in gui-init.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Persist the background color (and error state) through
the main menu and all submenus. Use warning
background color for destructive operations, error color
for errors.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Set and export currently-used defaults in gui-init, but still
allow for inidividual boards to override via config if desired.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Update_checksum was already changing files in /boot, befor checking for
gpg card. If no card is present, the user will end up in the recovery
next time instead of getting the same dialog again. Therefore, the
confirm_gpg_card should be checked before altering files.
The dead -u flag/$update_counter is used to mark the necessisty to
update the hash files now.
Currently, exiting the recovery shell results in a kernel panic,
necessitating a hard reset / power cycle. As this is less than ideal,
drop the exec and add a loop to restart the shell.
Addresses issue #833
Tested under qemu-coreboot-fbwhiptail
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Using 'let' in these scripts fails when evaluating to zero
for some reason, so replace with '$(())' which works as intended.
Test: Boot device selection menu shown properly when
new/unpartitioned drive installed.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Currently, /media is mounted once per boot, which causes issues
if a user need to change USB sticks, or unknowning performs an
operation that mounts /media and then needs to access a different
USB stick later (eg, updating the firmware).
To mitigate this, always unmount /media if mounted before scanning
for USB devices, so the user can choose the correct device at the
time of its use.
Additionally, add a unique exit code for user abort so we're not
treating it the same as a failure, and use it to prevent unnecessary
GUI prompts when cancelling selection of a USB device.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
For the handful of operations which need to be done with /boot
as the pwd, encapsulate them in subshells to ensure the pwd
doesn't unexpectedly change for other operations, as functions
which need to mount/unmount /boot may fail if the pwd isn't root.
Also, set the pwd to root at the start of detect_boot_device as an
added safety measure.
Test: run oem-factory-reset function, ensure it doesn't fail to
detect boot device due to incorrect working directory.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Move code duplicated across several GUI scripts into a common
gui_functions file and include/use that.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
If kexec-sign-config fails due to GPG key not present,
the double die() results in a kernel panic (and if it didn't,
/boot would be left mounted RW). Fix this by removing call to
die() and ensuring /boot remounted RO regardless checksum
update success or failure.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Add function to detect boot device. Start by checking
CONFIG_BOOT_DEV, then iterate thru all bootable partitions.
Check if partition is mountable, contains grub directory.
Update CONFIG_BOOT_DEV and mount on /boot if successful.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Initial card detection can sometimes fail, so prompt the user
to remove/reinsert their GPG card before retrying. Since
errexit is likely set, disable it prior to calling --card-status so
we can handle the error ourself, then re-set if necessary when done.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>